2
* Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3
* Copyright (C) 1999-2002 Internet Software Consortium.
5
* Permission to use, copy, modify, and distribute this software for any
6
* purpose with or without fee is hereby granted, provided that the above
7
* copyright notice and this permission notice appear in all copies.
9
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
* PERFORMANCE OF THIS SOFTWARE.
18
/* $Id: ntservice.c,v 1.3.2.1.10.3 2004/03/08 04:04:22 marka Exp $ */
23
#include <ntp_cmdargs.h>
24
#include <ntp_stdlib.h>
26
#include "ntservice.h"
27
#include "clockstuff.h"
28
#include "ntp_iocompletionport.h"
33
/* Handle to SCM for updating service status */
34
static SERVICE_STATUS_HANDLE hServiceStatus = 0;
35
static BOOL foreground = FALSE;
36
static char ConsoleTitle[128];
38
static char **glb_argv;
39
HANDLE hServDoneEvent = NULL;
40
extern volatile int debug;
41
extern char *progname;
43
void uninit_io_completion_port();
44
int ntpdmain(int argc, char *argv[]);
46
* Forward declarations
48
void ServiceControl(DWORD dwCtrlCode);
49
void ntservice_exit(void);
51
void WINAPI service_main( DWORD argc, LPTSTR *argv )
53
/* pass the global command line options on to the service */
54
ntpdmain( glb_argc, glb_argv );
59
* This is the entry point for the executable
60
* We can call ntpdmain() explicitly or via StartServiceCtrlDispatcher()
63
int main( int argc, char *argv[] )
68
/* Save the command line parameters */
72
/* Command line users should put -f in the options */
74
if (!_strnicmp(argv[i], "-d", 2) ||
75
!strcmp(argv[i], "-q") ||
76
!strcmp(argv[i], "--help") ||
77
!strcmp(argv[i], "-n")) {
85
/* run in console window */
86
exit(ntpdmain(argc, argv));
88
/* Start up as service */
90
SERVICE_TABLE_ENTRY dispatchTable[] = {
91
{ TEXT(NTP_DISPLAY_NAME), (LPSERVICE_MAIN_FUNCTION) service_main },
95
rc = StartServiceCtrlDispatcher(dispatchTable);
100
fprintf(stderr, "%s: unable to start as service, rc: %i\n\n", progname, rc);
102
fprintf(stderr, "\nUse -d, -q, --help or -n to run from the command line.\n");
110
* Initialize the Service by registering it.
115
/* Register handler with the SCM */
116
hServiceStatus = RegisterServiceCtrlHandler(NTP_DISPLAY_NAME,
117
(LPHANDLER_FUNCTION)ServiceControl);
118
if (!hServiceStatus) {
119
NTReportError(NTP_SERVICE_NAME,
120
"could not register service control handler");
121
UpdateSCM(SERVICE_STOPPED);
124
UpdateSCM(SERVICE_RUNNING);
126
strcpy(ConsoleTitle, "NTP Version ");
127
strcat(ConsoleTitle, Version);
128
SetConsoleTitle(ConsoleTitle);
131
atexit( ntservice_exit );
134
* Routine to check if this is a service or a foreground program
137
ntservice_isservice() {
140
/* service_ctrl - control handler for NTP service
141
* signals the service_main routine of start/stop requests
142
* from the control panel or other applications making
146
ntservice_exit( void )
149
if (!foreground) { /* did not become a service, simply exit */
150
/* service mode, need to have the service_main routine
151
* register with the service control manager that the
152
* service has stopped running, before exiting
154
UpdateSCM(SERVICE_STOPPED);
156
uninit_io_completion_port();
161
msyslog(LOG_INFO, "ntservice: The Network Time Protocol Service has stopped.");
164
_CrtDumpMemoryLeaks();
169
* ServiceControl(): Handles requests from the SCM and passes them on
173
ServiceControl(DWORD dwCtrlCode) {
174
/* Handle the requested control code */
175
HANDLE exitEvent = get_exit_event();
179
case SERVICE_CONTROL_SHUTDOWN:
180
case SERVICE_CONTROL_STOP:
181
UpdateSCM(SERVICE_STOP_PENDING);
182
if (exitEvent != NULL) {
188
case SERVICE_CONTROL_PAUSE:
189
case SERVICE_CONTROL_CONTINUE:
190
case SERVICE_CONTROL_INTERROGATE:
194
UpdateSCM(SERVICE_RUNNING);
198
* Tell the Service Control Manager the state of the service.
200
void UpdateSCM(DWORD state) {
202
static DWORD dwState = SERVICE_STOPPED;
204
if (hServiceStatus) {
208
memset(&ss, 0, sizeof(SERVICE_STATUS));
209
ss.dwServiceType |= SERVICE_WIN32_OWN_PROCESS;
210
ss.dwCurrentState = dwState;
211
ss.dwControlsAccepted = SERVICE_ACCEPT_STOP |
212
SERVICE_ACCEPT_SHUTDOWN;
214
ss.dwServiceSpecificExitCode = 0;
215
ss.dwWin32ExitCode = NO_ERROR;
216
ss.dwWaitHint = dwState == SERVICE_STOP_PENDING ? 5000 : 1000;
218
if (!SetServiceStatus(hServiceStatus, &ss)) {
219
ss.dwCurrentState = SERVICE_STOPPED;
220
SetServiceStatus(hServiceStatus, &ss);
230
HANDLE exitEvent = get_exit_event();
232
switch (dwCtrlType) {
234
case CTRL_BREAK_EVENT :
244
printf("debug level %d\n", debug);
249
case CTRL_CLOSE_EVENT :
250
case CTRL_SHUTDOWN_EVENT :
251
if (exitEvent != NULL) {