394 lines
10 KiB
C
394 lines
10 KiB
C
/********************************************************************/
|
||
/** Copyright(c) 1989 Microsoft Corporation. **/
|
||
/********************************************************************/
|
||
|
||
//***
|
||
//
|
||
// Filename: main.c
|
||
//
|
||
// Description: This module contains the main procedure of the AFP server
|
||
// service. It will contain code to initialize and install
|
||
// itself and the kernel-mode AFP Server. It also contains
|
||
// code to respond to the server controller. It will also
|
||
// handle service shutdown.
|
||
//
|
||
// ??? Does the service controller log start/stop events etc ??
|
||
// if not log it.
|
||
//
|
||
// History:
|
||
// May 11,1990. NarenG Created original version.
|
||
//
|
||
#define DEFINE_AFP_GLOBALS // This will cause AfpGlobals to be defined.
|
||
#include "afpsvcp.h"
|
||
|
||
// Prototypes of functions used only within this module.
|
||
//
|
||
VOID
|
||
AfpMain(
|
||
IN DWORD argc,
|
||
IN LPWSTR * lpwsServiceArgs
|
||
);
|
||
|
||
VOID
|
||
AfpCleanupAndExit(
|
||
IN DWORD dwError
|
||
);
|
||
|
||
VOID
|
||
AfpControlResponse(
|
||
IN DWORD dwControlCode
|
||
);
|
||
|
||
|
||
//**
|
||
//
|
||
// Call: main.c
|
||
//
|
||
// Returns: none.
|
||
//
|
||
// Description: Will simply register the entry point of the AFP server
|
||
// service with the service controller. The service controller
|
||
// will capture this thread. It will be freed only when
|
||
// the service is shutdown. At that point we will simply exit
|
||
// the process.
|
||
//
|
||
void
|
||
_cdecl
|
||
main( int argc, unsigned char * argv[] )
|
||
{
|
||
SERVICE_TABLE_ENTRY AfpServiceDispatchTable[2];
|
||
|
||
#ifdef DBG
|
||
|
||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||
COORD coord;
|
||
(VOID)AllocConsole( );
|
||
(VOID)GetConsoleScreenBufferInfo( GetStdHandle(STD_OUTPUT_HANDLE),
|
||
&csbi
|
||
);
|
||
coord.X = (SHORT)(csbi.srWindow.Right - csbi.srWindow.Left + 1);
|
||
coord.Y = (SHORT)((csbi.srWindow.Bottom - csbi.srWindow.Top + 1) * 20);
|
||
(VOID)SetConsoleScreenBufferSize( GetStdHandle(STD_OUTPUT_HANDLE),
|
||
coord
|
||
);
|
||
#endif
|
||
|
||
AFP_UNREFERENCED( argc );
|
||
AFP_UNREFERENCED( argv );
|
||
|
||
|
||
AfpServiceDispatchTable[0].lpServiceName = AFP_SERVICE_NAME;
|
||
AfpServiceDispatchTable[0].lpServiceProc = AfpMain;
|
||
AfpServiceDispatchTable[1].lpServiceName = NULL;
|
||
AfpServiceDispatchTable[1].lpServiceProc = NULL;
|
||
|
||
if ( !StartServiceCtrlDispatcher( AfpServiceDispatchTable ) )
|
||
AfpLogEvent( AFPLOG_CANT_START, 0, NULL,
|
||
GetLastError(), EVENTLOG_ERROR_TYPE );
|
||
|
||
ExitProcess(0);
|
||
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: AfpMain
|
||
//
|
||
// Returns: none.
|
||
//
|
||
// Description: This is the main procedure for the Afp Server Service. It
|
||
// will be called when the service is supposed to start itself.
|
||
// It will do all service wide initialization.
|
||
//
|
||
VOID
|
||
AfpMain( DWORD argc, // Command line arguments. Will be ignored.
|
||
LPWSTR * lpwsServiceArgs
|
||
)
|
||
{
|
||
DWORD dwRetCode;
|
||
|
||
|
||
AFP_UNREFERENCED( argc );
|
||
AFP_UNREFERENCED( lpwsServiceArgs );
|
||
|
||
// NULL out all the globals
|
||
//
|
||
ZeroMemory( (LPBYTE)&AfpGlobals, sizeof(AfpGlobals) );
|
||
|
||
// Register the service control handler with the service controller
|
||
//
|
||
AfpGlobals.hServiceStatus = RegisterServiceCtrlHandler(AFP_SERVICE_NAME,
|
||
AfpControlResponse );
|
||
|
||
if ( AfpGlobals.hServiceStatus == (SERVICE_STATUS_HANDLE)0 ) {
|
||
AfpLogEvent( AFPLOG_CANT_START, 0, NULL,
|
||
GetLastError(), EVENTLOG_ERROR_TYPE );
|
||
AfpCleanupAndExit( GetLastError() );
|
||
return;
|
||
}
|
||
|
||
AfpGlobals.ServiceStatus.dwServiceType = SERVICE_WIN32;
|
||
AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
|
||
AfpGlobals.ServiceStatus.dwControlsAccepted = 0;
|
||
AfpGlobals.ServiceStatus.dwWin32ExitCode = NO_ERROR;
|
||
AfpGlobals.ServiceStatus.dwServiceSpecificExitCode= 0;
|
||
AfpGlobals.ServiceStatus.dwCheckPoint = 1;
|
||
AfpGlobals.ServiceStatus.dwWaitHint =AFP_SERVICE_INSTALL_TIME;
|
||
|
||
AfpAnnounceServiceStatus();
|
||
|
||
// Read in registry information and initialize the kernel-mode
|
||
// server. Initialize the server to accept RPC calls. Initialize
|
||
// all global vriables etc.
|
||
//
|
||
if ( dwRetCode = AfpInitialize() )
|
||
{
|
||
if (AfpGlobals.dwServerState & AFPSTATE_BLOCKED_ON_DOMINFO)
|
||
{
|
||
AfpCleanupAndExit( NO_ERROR );
|
||
}
|
||
else
|
||
{
|
||
AfpCleanupAndExit( dwRetCode );
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
// Set the MAC bit for NetServerEnum
|
||
//
|
||
if ( !I_ScSetServiceBits( AfpGlobals.hServiceStatus,
|
||
SV_TYPE_AFP,
|
||
TRUE,
|
||
TRUE,
|
||
NULL ))
|
||
{
|
||
|
||
dwRetCode = GetLastError();
|
||
AfpLogEvent( AFPLOG_CANT_START, 0, NULL,
|
||
GetLastError(), EVENTLOG_ERROR_TYPE );
|
||
AfpCleanupAndExit( dwRetCode );
|
||
return;
|
||
}
|
||
|
||
// now tell the service controller that we are up
|
||
//
|
||
if (AfpGlobals.ServiceStatus.dwCurrentState == SERVICE_START_PENDING)
|
||
{
|
||
AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
||
AfpGlobals.ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
|
||
SERVICE_ACCEPT_PAUSE_CONTINUE;
|
||
AfpGlobals.ServiceStatus.dwCheckPoint = 0;
|
||
AfpGlobals.ServiceStatus.dwWaitHint = 0;
|
||
|
||
AfpAnnounceServiceStatus();
|
||
}
|
||
|
||
|
||
// Start listening for RPC admin client calls. This will block
|
||
// until RpcMgmtStopServerListening is called while processing a
|
||
// STOP_SERVICE control request.
|
||
//
|
||
if ( dwRetCode = RpcServerListen( 1,
|
||
RPC_C_LISTEN_MAX_CALLS_DEFAULT,
|
||
0 ) ) // Blocking mode
|
||
{
|
||
|
||
AfpLogEvent( AFPLOG_CANT_INIT_RPC, 0, NULL,
|
||
dwRetCode, EVENTLOG_ERROR_TYPE );
|
||
}
|
||
|
||
AfpCleanupAndExit( dwRetCode );
|
||
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: AfpCleanupAndExit
|
||
//
|
||
// Returns: none
|
||
//
|
||
// Description: Will free any allocated memory, deinitialize RPC, deinitialize
|
||
// the kernel-mode server and unload it if it was loaded.
|
||
// This could have been called due to an error on SERVICE_START
|
||
// or normal termination.
|
||
//
|
||
VOID
|
||
AfpCleanupAndExit(
|
||
IN DWORD dwError
|
||
)
|
||
{
|
||
|
||
AFP_PRINT( ("AFPSVC_main: Cleaning up and exiting Code = %d\n", dwError));
|
||
|
||
// Tear down and free everything
|
||
//
|
||
AfpTerminate();
|
||
|
||
if ( dwError == NO_ERROR )
|
||
AfpGlobals.ServiceStatus.dwWin32ExitCode = NO_ERROR;
|
||
else {
|
||
AfpGlobals.ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
|
||
//AFP_ASSERT(0);
|
||
}
|
||
|
||
AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||
AfpGlobals.ServiceStatus.dwCheckPoint = 0;
|
||
AfpGlobals.ServiceStatus.dwWaitHint = 0;
|
||
AfpGlobals.ServiceStatus.dwServiceSpecificExitCode = dwError;
|
||
|
||
AfpAnnounceServiceStatus();
|
||
|
||
return;
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: AfpControlResponse
|
||
//
|
||
// Returns: none
|
||
//
|
||
// Description: Will respond to control requests from the service controller.
|
||
//
|
||
VOID
|
||
AfpControlResponse( IN DWORD dwControlCode )
|
||
{
|
||
AFP_REQUEST_PACKET AfpRequestPkt;
|
||
DWORD dwRetCode;
|
||
|
||
switch( dwControlCode ) {
|
||
|
||
case SERVICE_CONTROL_STOP:
|
||
|
||
if ( (AfpGlobals.ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
|
||
||
|
||
(AfpGlobals.ServiceStatus.dwCurrentState == SERVICE_STOPPED ))
|
||
break;
|
||
|
||
// Announce that we are stopping
|
||
//
|
||
AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
||
AfpGlobals.ServiceStatus.dwControlsAccepted = 0;
|
||
AfpGlobals.ServiceStatus.dwCheckPoint = 1;
|
||
AfpGlobals.ServiceStatus.dwWaitHint = AFP_SERVICE_STOP_TIME;
|
||
|
||
AfpAnnounceServiceStatus();
|
||
|
||
// if srvrhlpr thread is blocked retrying to get domain info, unblock it
|
||
SetEvent(AfpGlobals.heventSrvrHlprSpecial);
|
||
|
||
// if srvrhlpr thread was blocked, no more init was done, so we're done
|
||
if (AfpGlobals.dwServerState & AFPSTATE_BLOCKED_ON_DOMINFO)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// This call will unblock the main thread that had called
|
||
// RpcServerListen. We let that thread do the announcing
|
||
// while cleaning up.
|
||
//
|
||
if ( (dwRetCode =
|
||
RpcMgmtStopServerListening( (RPC_BINDING_HANDLE)NULL ))
|
||
!= RPC_S_OK )
|
||
{
|
||
ASSERT (0);
|
||
}
|
||
|
||
|
||
return;
|
||
|
||
case SERVICE_CONTROL_PAUSE:
|
||
|
||
if ( (AfpGlobals.ServiceStatus.dwCurrentState == SERVICE_PAUSE_PENDING)
|
||
||
|
||
(AfpGlobals.ServiceStatus.dwCurrentState == SERVICE_PAUSED ))
|
||
break;
|
||
|
||
AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_PAUSE_PENDING;
|
||
AfpGlobals.ServiceStatus.dwControlsAccepted = 0;
|
||
AfpGlobals.ServiceStatus.dwCheckPoint = 0;
|
||
AfpGlobals.ServiceStatus.dwWaitHint = AFP_SERVICE_PAUSE_TIME;
|
||
|
||
AfpAnnounceServiceStatus();
|
||
|
||
|
||
// Tell the kernel-mode that we want to pause.
|
||
//
|
||
AfpRequestPkt.dwRequestCode = OP_SERVICE_PAUSE;
|
||
AfpRequestPkt.dwApiType = AFP_API_TYPE_COMMAND;
|
||
|
||
dwRetCode = AfpServerIOCtrl( &AfpRequestPkt );
|
||
|
||
AFP_ASSERT( dwRetCode == NO_ERROR );
|
||
|
||
AfpGlobals.ServiceStatus.dwCheckPoint = 0;
|
||
AfpGlobals.ServiceStatus.dwWaitHint = 0;
|
||
AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_PAUSED;
|
||
AfpGlobals.ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
|
||
SERVICE_ACCEPT_PAUSE_CONTINUE;
|
||
break;
|
||
|
||
case SERVICE_CONTROL_CONTINUE:
|
||
|
||
if ( (AfpGlobals.ServiceStatus.dwCurrentState==SERVICE_CONTINUE_PENDING)
|
||
||
|
||
(AfpGlobals.ServiceStatus.dwCurrentState == SERVICE_RUNNING ))
|
||
break;
|
||
|
||
AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_CONTINUE_PENDING;
|
||
AfpGlobals.ServiceStatus.dwControlsAccepted = 0;
|
||
AfpGlobals.ServiceStatus.dwCheckPoint = 0;
|
||
AfpGlobals.ServiceStatus.dwWaitHint = AFP_SERVICE_CONTINUE_TIME;
|
||
|
||
AfpAnnounceServiceStatus();
|
||
|
||
// Tell the kernel-mode that we want to continue.
|
||
//
|
||
AfpRequestPkt.dwRequestCode = OP_SERVICE_CONTINUE;
|
||
AfpRequestPkt.dwApiType = AFP_API_TYPE_COMMAND;
|
||
|
||
dwRetCode = AfpServerIOCtrl( &AfpRequestPkt );
|
||
|
||
AFP_ASSERT( dwRetCode == NO_ERROR );
|
||
|
||
AfpGlobals.ServiceStatus.dwCheckPoint = 0;
|
||
AfpGlobals.ServiceStatus.dwWaitHint = 0;
|
||
AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
||
AfpGlobals.ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
|
||
SERVICE_ACCEPT_PAUSE_CONTINUE;
|
||
|
||
break;
|
||
|
||
case SERVICE_CONTROL_INTERROGATE:
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
|
||
}
|
||
|
||
AfpAnnounceServiceStatus();
|
||
}
|
||
|
||
//**
|
||
//
|
||
// Call: AfpAnnounceServiceStatus
|
||
//
|
||
// Returns: none
|
||
//
|
||
// Description: Will simly call SetServiceStatus to inform the service
|
||
// control manager of this service's current status.
|
||
//
|
||
VOID
|
||
AfpAnnounceServiceStatus( VOID )
|
||
{
|
||
BOOL dwRetCode;
|
||
|
||
|
||
dwRetCode = SetServiceStatus( AfpGlobals.hServiceStatus,
|
||
&(AfpGlobals.ServiceStatus) );
|
||
|
||
AFP_ASSERT( dwRetCode == TRUE );
|
||
|
||
}
|