|
|
/********************************************************************/ /** 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 );
}
|