#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <ntp_stdlib.h>
#include "syslog.h"
#include "ntpd.h"
#include "ntservice.h"
#include "clockstuff.h"
#include "ntp_iocompletionport.h"
#include "ntpd-opts.h"
#include "isc/win32os.h"
#include <ssl_applink.c>
static SERVICE_STATUS_HANDLE hServiceStatus = 0;
static BOOL foreground = FALSE;
static BOOL computer_shutting_down = FALSE;
static int glb_argc;
static char **glb_argv;
HANDLE hServDoneEvent = NULL;
extern int accept_wildcard_if_for_winnt;
void uninit_io_completion_port();
int ntpdmain(int argc, char *argv[]);
void WINAPI ServiceControl(DWORD dwCtrlCode);
void ntservice_exit(void);
#ifdef WRAP_DBG_MALLOC
void *wrap_dbg_malloc(size_t s, const char *f, int l);
void *wrap_dbg_realloc(void *p, size_t s, const char *f, int l);
void wrap_dbg_free(void *p);
void wrap_dbg_free_ex(void *p, const char *f, int l);
#endif
void WINAPI
service_main(
DWORD argc,
LPTSTR *argv
)
{
if (argc > 1) {
glb_argc = argc;
glb_argv = argv;
}
ntpdmain(glb_argc, glb_argv);
}
int main(
int argc,
char ** argv
)
{
int rc;
int argc_after_opts;
char ** argv_after_opts;
ssl_applink();
glb_argc = argc;
glb_argv = argv;
if (isc_win32os_majorversion() <= 4)
accept_wildcard_if_for_winnt = TRUE;
argc_after_opts = argc;
argv_after_opts = argv;
parse_cmdline_opts(&argc_after_opts, &argv_after_opts);
if (HAVE_OPT(QUIT)
|| HAVE_OPT(SAVECONFIGQUIT)
|| HAVE_OPT(HELP)
#ifdef DEBUG
|| OPT_VALUE_SET_DEBUG_LEVEL != 0
#endif
|| HAVE_OPT(NOFORK))
foreground = TRUE;
if (foreground)
rc = ntpdmain(argc, argv);
else {
SERVICE_TABLE_ENTRY dispatchTable[] = {
{ TEXT(NTP_DISPLAY_NAME), service_main },
{ NULL, NULL }
};
rc = StartServiceCtrlDispatcher(dispatchTable);
if (rc)
rc = 0;
else {
rc = GetLastError();
fprintf(stderr,
"%s: unable to start as service:\n"
"%s\n"
"Use -d, -q, -n, -?, --help or "
"--saveconfigquit to run "
"interactive.\n",
argv[0], ntp_strerror(rc));
}
}
return rc;
}
void
ntservice_init() {
char ConsoleTitle[256];
if (!foreground) {
hServiceStatus = RegisterServiceCtrlHandler(NTP_DISPLAY_NAME,
ServiceControl);
if (!hServiceStatus) {
NTReportError(NTP_SERVICE_NAME,
"could not register service control handler");
exit(1);
}
UpdateSCM(SERVICE_RUNNING);
} else {
snprintf(ConsoleTitle, sizeof(ConsoleTitle),
"NTP Version %s", Version);
ConsoleTitle[sizeof(ConsoleTitle) - 1] = '\0';
SetConsoleTitle(ConsoleTitle);
}
#ifdef _CRTDBG_MAP_ALLOC
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF
| _CRTDBG_LEAK_CHECK_DF
| _CRTDBG_CHECK_ALWAYS_DF
#ifdef MALLOC_LINT
| _CRTDBG_DELAY_FREE_MEM_DF
#endif
);
#ifdef DOES_NOT_WORK
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
#endif
#endif
atexit( ntservice_exit );
}
BOOL
ntservice_systemisshuttingdown() {
return computer_shutting_down;
}
void
ntservice_exit( void )
{
uninit_io_completion_port();
Sleep( 200 );
reset_winnt_time();
msyslog(LOG_INFO, "ntservice: The Network Time Protocol Service is stopping.");
if (!foreground) {
UpdateSCM(SERVICE_STOPPED);
}
}
void WINAPI
ServiceControl(
DWORD dwCtrlCode
)
{
static const char * const msg_tab[2] = {
"explicit stop",
"system shutdown"
};
switch (dwCtrlCode) {
case SERVICE_CONTROL_SHUTDOWN:
computer_shutting_down = TRUE;
case SERVICE_CONTROL_STOP:
if (WaitableExitEventHandle != NULL) {
msyslog(LOG_INFO, "SCM requests stop (%s)",
msg_tab[!!computer_shutting_down]);
UpdateSCM(SERVICE_STOP_PENDING);
SetEvent(WaitableExitEventHandle);
Sleep(100); break;
}
msyslog(LOG_ERR, "SCM requests stop (%s), but have no exit event!",
msg_tab[!!computer_shutting_down]);
case SERVICE_CONTROL_PAUSE:
case SERVICE_CONTROL_CONTINUE:
case SERVICE_CONTROL_INTERROGATE:
default:
UpdateSCM(SERVICE_RUNNING);
break;
}
}
void UpdateSCM(DWORD state) {
SERVICE_STATUS ss;
static DWORD dwState = SERVICE_STOPPED;
if (hServiceStatus) {
if (state)
dwState = state;
ZERO(ss);
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;
SetServiceStatus(hServiceStatus, &ss);
}
}
BOOL WINAPI
OnConsoleEvent(
DWORD dwCtrlType
)
{
switch (dwCtrlType) {
#ifdef DEBUG
case CTRL_BREAK_EVENT:
if (debug > 0) {
debug <<= 1;
}
else {
debug = 1;
}
if (debug > 8) {
debug = 0;
}
msyslog(LOG_DEBUG, "debug level %d", debug);
break;
#else
case CTRL_BREAK_EVENT:
break;
#endif
case CTRL_C_EVENT:
case CTRL_CLOSE_EVENT:
case CTRL_SHUTDOWN_EVENT:
if (WaitableExitEventHandle != NULL) {
SetEvent(WaitableExitEventHandle);
Sleep(100); }
break;
default :
return FALSE;
}
return TRUE;
}