#include <config.h>
#include <stdio.h>
#include <ntp_cmdargs.h>
#include <ntp_stdlib.h>
#include "syslog.h"
#include "ntservice.h"
#include "clockstuff.h"
#include "ntp_iocompletionport.h"
#ifdef DEBUG
#include <crtdbg.h>
#endif
static SERVICE_STATUS_HANDLE hServiceStatus = 0;
static BOOL foreground = FALSE;
static char ConsoleTitle[128];
static int glb_argc;
static char **glb_argv;
HANDLE hServDoneEvent = NULL;
extern volatile int debug;
extern char *progname;
void uninit_io_completion_port();
int ntpdmain(int argc, char *argv[]);
void ServiceControl(DWORD dwCtrlCode);
void ntservice_exit(void);
void WINAPI service_main( DWORD argc, LPTSTR *argv )
{
ntpdmain( glb_argc, glb_argv );
}
int main( int argc, char *argv[] )
{
int rc;
int i = 1;
glb_argc = argc;
glb_argv = argv;
while (argv[i]) {
if (!_strnicmp(argv[i], "-d", 2) ||
!strcmp(argv[i], "-q") ||
!strcmp(argv[i], "--help") ||
!strcmp(argv[i], "-n")) {
foreground = TRUE;
break;
}
i++;
}
if (foreground) {
exit(ntpdmain(argc, argv));
} else {
SERVICE_TABLE_ENTRY dispatchTable[] = {
{ TEXT(NTP_DISPLAY_NAME), (LPSERVICE_MAIN_FUNCTION) service_main },
{ NULL, NULL }
};
rc = StartServiceCtrlDispatcher(dispatchTable);
if (!rc) {
progname = argv[0];
rc = GetLastError();
#ifdef DEBUG
fprintf(stderr, "%s: unable to start as service, rc: %i\n\n", progname, rc);
#endif
fprintf(stderr, "\nUse -d, -q, --help or -n to run from the command line.\n");
exit(rc);
}
}
exit(0);
}
void
ntservice_init() {
if (!foreground) {
hServiceStatus = RegisterServiceCtrlHandler(NTP_DISPLAY_NAME,
(LPHANDLER_FUNCTION)ServiceControl);
if (!hServiceStatus) {
NTReportError(NTP_SERVICE_NAME,
"could not register service control handler");
UpdateSCM(SERVICE_STOPPED);
exit(1);
}
UpdateSCM(SERVICE_RUNNING);
} else {
strcpy(ConsoleTitle, "NTP Version ");
strcat(ConsoleTitle, Version);
SetConsoleTitle(ConsoleTitle);
}
atexit( ntservice_exit );
}
BOOL
ntservice_isservice() {
return(!foreground);
}
void
ntservice_exit( void )
{
if (!foreground) {
UpdateSCM(SERVICE_STOPPED);
}
uninit_io_completion_port();
Sleep( 200 );
reset_winnt_time();
msyslog(LOG_INFO, "ntservice: The Network Time Protocol Service has stopped.");
# ifdef DEBUG
_CrtDumpMemoryLeaks();
# endif
}
void
ServiceControl(DWORD dwCtrlCode) {
HANDLE exitEvent = get_exit_event();
switch(dwCtrlCode) {
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
UpdateSCM(SERVICE_STOP_PENDING);
if (exitEvent != NULL) {
SetEvent(exitEvent);
Sleep( 100 ); }
return;
case SERVICE_CONTROL_PAUSE:
case SERVICE_CONTROL_CONTINUE:
case SERVICE_CONTROL_INTERROGATE:
default:
break;
}
UpdateSCM(SERVICE_RUNNING);
}
void UpdateSCM(DWORD state) {
SERVICE_STATUS ss;
static DWORD dwState = SERVICE_STOPPED;
if (hServiceStatus) {
if (state)
dwState = state;
memset(&ss, 0, sizeof(SERVICE_STATUS));
ss.dwServiceType |= SERVICE_WIN32_OWN_PROCESS;
ss.dwCurrentState = dwState;
ss.dwControlsAccepted = SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_SHUTDOWN;
ss.dwCheckPoint = 0;
ss.dwServiceSpecificExitCode = 0;
ss.dwWin32ExitCode = NO_ERROR;
ss.dwWaitHint = dwState == SERVICE_STOP_PENDING ? 5000 : 1000;
if (!SetServiceStatus(hServiceStatus, &ss)) {
ss.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hServiceStatus, &ss);
}
}
}
BOOL WINAPI
OnConsoleEvent(
DWORD dwCtrlType
)
{
HANDLE exitEvent = get_exit_event();
switch (dwCtrlType) {
#ifdef DEBUG
case CTRL_BREAK_EVENT :
if (debug > 0) {
debug <<= 1;
}
else {
debug = 1;
}
if (debug > 8) {
debug = 0;
}
printf("debug level %d\n", debug);
break ;
#endif
case CTRL_C_EVENT :
case CTRL_CLOSE_EVENT :
case CTRL_SHUTDOWN_EVENT :
if (exitEvent != NULL) {
SetEvent(exitEvent);
Sleep( 100 ); }
break;
default :
return FALSE;
}
return TRUE;;
}