Annotation of embedaddon/ntp/ports/winnt/ntpd/ntservice.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3: * Copyright (C) 1999-2002 Internet Software Consortium.
4: *
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.
8: *
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.
16: */
17:
18: /* $Id: ntservice.c,v 1.3.2.1.10.3 2004/03/08 04:04:22 marka Exp $ */
19:
20: #ifdef HAVE_CONFIG_H
21: # include <config.h>
22: #endif
23:
24: #include <stdio.h>
25:
26: #include <ntp_cmdargs.h>
27: #include <ntp_stdlib.h>
28: #include "syslog.h"
29: #include "ntservice.h"
30: #include "clockstuff.h"
31: #include "ntp_iocompletionport.h"
32: #include "isc/win32os.h"
33: #include <ssl_applink.c>
34:
35:
36: /*
37: * Globals
38: */
39: static SERVICE_STATUS_HANDLE hServiceStatus = 0;
40: static BOOL foreground = FALSE;
41: static BOOL computer_shutting_down = FALSE;
42: static int glb_argc;
43: static char **glb_argv;
44: HANDLE hServDoneEvent = NULL;
45: extern volatile int debug;
46: extern int accept_wildcard_if_for_winnt;
47:
48: /*
49: * Forward declarations
50: */
51: void uninit_io_completion_port();
52: int ntpdmain(int argc, char *argv[]);
53: void WINAPI ServiceControl(DWORD dwCtrlCode);
54: void ntservice_exit(void);
55:
56: #ifdef WRAP_DBG_MALLOC
57: void *wrap_dbg_malloc(size_t s, const char *f, int l);
58: void *wrap_dbg_realloc(void *p, size_t s, const char *f, int l);
59: void wrap_dbg_free(void *p);
60: #endif
61:
62: void WINAPI service_main( DWORD argc, LPTSTR *argv )
63: {
64: if ( argc > 1 )
65: {
66: /*
67: * Let command line parameters from the Windows SCM GUI
68: * override the standard parameters from the ImagePath registry key.
69: */
70: glb_argc = argc;
71: glb_argv = argv;
72: }
73:
74: ntpdmain( glb_argc, glb_argv );
75: }
76:
77:
78: /*
79: * This is the entry point for the executable
80: * We can call ntpdmain() explicitly or via StartServiceCtrlDispatcher()
81: * as we need to.
82: */
83: int main( int argc, char *argv[] )
84: {
85: int rc;
86: int i = 1;
87:
88:
89: ssl_applink();
90:
91: /* Save the command line parameters */
92: glb_argc = argc;
93: glb_argv = argv;
94:
95: /* Under original Windows NT we must not discard the wildcard */
96: /* socket to workaround a bug in NT's getsockname(). */
97: if (isc_win32os_majorversion() <= 4)
98: accept_wildcard_if_for_winnt = TRUE;
99:
100: /*
101: * This is a hack in the Windows port of ntpd. Before the
102: * portable ntpd libopts processing of the command line, we
103: * need to know if we're "daemonizing" (attempting to start as
104: * a service). There is undoubtedly a better way. Legitimate
105: * option combinations are broken by this code , such as:
106: * ntpd -nc debug.conf
107: */
108: while (argv[i]) {
109: if (!_strnicmp(argv[i], "-d", 2)
110: || !strcmp(argv[i], "--debug_level")
111: || !strcmp(argv[i], "--set-debug_level")
112: || !strcmp(argv[i], "-q")
113: || !strcmp(argv[i], "--quit")
114: || !strcmp(argv[i], "-?")
115: || !strcmp(argv[i], "--help")
116: || !_strnicmp(argv[i], "-n", 2)
117: || !strcmp(argv[i], "--nofork")
118: || !strcmp(argv[i], "--saveconfigquit")) {
119: foreground = TRUE;
120: break;
121: }
122: i++;
123: }
124:
125: if (foreground) /* run in console window */
126: rc = ntpdmain(argc, argv);
127: else {
128: /* Start up as service */
129:
130: SERVICE_TABLE_ENTRY dispatchTable[] = {
131: { TEXT(NTP_DISPLAY_NAME), service_main },
132: { NULL, NULL }
133: };
134:
135: rc = StartServiceCtrlDispatcher(dispatchTable);
136: if (rc)
137: rc = 0;
138: else {
139: rc = GetLastError();
140: #ifdef DEBUG
141: fprintf(stderr, "%s: unable to start as service, rc: %i\n\n", argv[0], rc);
142: #endif
143: fprintf(stderr, "\nUse -d, -q, --help or -n to run from the command line.\n");
144: }
145: }
146: return rc;
147: }
148:
149: /*
150: * Initialize the Service by registering it.
151: */
152: void
153: ntservice_init() {
154: char ConsoleTitle[256];
155:
156: if (!foreground) {
157: /* Register handler with the SCM */
158: hServiceStatus = RegisterServiceCtrlHandler(NTP_DISPLAY_NAME,
159: ServiceControl);
160: if (!hServiceStatus) {
161: NTReportError(NTP_SERVICE_NAME,
162: "could not register service control handler");
163: exit(1);
164: }
165: UpdateSCM(SERVICE_RUNNING);
166: } else {
167: strcpy(ConsoleTitle, "NTP Version ");
168: strcat(ConsoleTitle, Version);
169: SetConsoleTitle(ConsoleTitle);
170: }
171:
172: #ifdef _CRTDBG_MAP_ALLOC
173: /* ask the runtime to dump memory leaks at exit */
174: _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF
175: | _CRTDBG_LEAK_CHECK_DF /* report on leaks at exit */
176: | _CRTDBG_CHECK_ALWAYS_DF /* Check heap every alloc/dealloc */
177: #ifdef MALLOC_LINT
178: | _CRTDBG_DELAY_FREE_MEM_DF /* Don't actually free memory */
179: #endif
180: );
181: #ifdef DOES_NOT_WORK
182: /*
183: * hart: I haven't seen this work, running ntpd.exe -n from a shell
184: * to both a file and the debugger output window. Docs indicate it
185: * should cause leak report to go to stderr, but it's only seen if
186: * ntpd runs under a debugger (in the debugger's output), even with
187: * this block of code enabled.
188: */
189: _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
190: _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
191: #endif
192: #endif /* using MS debug C runtime heap, _CRTDBG_MAP_ALLOC */
193:
194: atexit( ntservice_exit );
195: }
196:
197: /*
198: * Routine to check if this is a service or a foreground program
199: */
200: BOOL
201: ntservice_isservice() {
202: return(!foreground);
203: }
204:
205: /*
206: * Routine to check if the service is stopping
207: * because the computer is shutting down
208: */
209: BOOL
210: ntservice_systemisshuttingdown() {
211: return computer_shutting_down;
212: }
213:
214: void
215: ntservice_exit( void )
216: {
217: uninit_io_completion_port();
218: Sleep( 200 ); //##++
219:
220: reset_winnt_time();
221:
222: msyslog(LOG_INFO, "ntservice: The Network Time Protocol Service is stopping.");
223:
224: if (!foreground) {
225: /* service mode, need to have the service_main routine
226: * register with the service control manager that the
227: * service has stopped running, before exiting
228: */
229: UpdateSCM(SERVICE_STOPPED);
230: }
231: }
232:
233: /*
234: * ServiceControl(): Handles requests from the SCM and passes them on
235: * to the service.
236: */
237: void WINAPI
238: ServiceControl(DWORD dwCtrlCode) {
239: /* Handle the requested control code */
240: HANDLE exitEvent = get_exit_event();
241:
242: switch(dwCtrlCode) {
243:
244: case SERVICE_CONTROL_SHUTDOWN:
245: computer_shutting_down = TRUE;
246: /* fall through to stop case */
247:
248: case SERVICE_CONTROL_STOP:
249: if (exitEvent != NULL) {
250: SetEvent(exitEvent);
251: UpdateSCM(SERVICE_STOP_PENDING);
252: Sleep( 100 ); //##++
253: }
254: return;
255:
256: case SERVICE_CONTROL_PAUSE:
257: case SERVICE_CONTROL_CONTINUE:
258: case SERVICE_CONTROL_INTERROGATE:
259: default:
260: break;
261: }
262: UpdateSCM(SERVICE_RUNNING);
263: }
264:
265: /*
266: * Tell the Service Control Manager the state of the service.
267: */
268: void UpdateSCM(DWORD state) {
269: SERVICE_STATUS ss;
270: static DWORD dwState = SERVICE_STOPPED;
271:
272: if (hServiceStatus) {
273: if (state)
274: dwState = state;
275:
276: memset(&ss, 0, sizeof(SERVICE_STATUS));
277: ss.dwServiceType |= SERVICE_WIN32_OWN_PROCESS;
278: ss.dwCurrentState = dwState;
279: ss.dwControlsAccepted = SERVICE_ACCEPT_STOP |
280: SERVICE_ACCEPT_SHUTDOWN;
281: ss.dwCheckPoint = 0;
282: ss.dwServiceSpecificExitCode = 0;
283: ss.dwWin32ExitCode = NO_ERROR;
284: ss.dwWaitHint = dwState == SERVICE_STOP_PENDING ? 5000 : 1000;
285:
286: SetServiceStatus(hServiceStatus, &ss);
287: }
288: }
289:
290: BOOL WINAPI
291: OnConsoleEvent(
292: DWORD dwCtrlType
293: )
294: {
295: HANDLE exitEvent = get_exit_event();
296:
297: switch (dwCtrlType) {
298: #ifdef DEBUG
299: case CTRL_BREAK_EVENT:
300: if (debug > 0) {
301: debug <<= 1;
302: }
303: else {
304: debug = 1;
305: }
306: if (debug > 8) {
307: debug = 0;
308: }
309: msyslog(LOG_DEBUG, "debug level %d", debug);
310: break;
311: #else
312: case CTRL_BREAK_EVENT:
313: break;
314: #endif
315:
316: case CTRL_C_EVENT:
317: case CTRL_CLOSE_EVENT:
318: case CTRL_SHUTDOWN_EVENT:
319: if (exitEvent != NULL) {
320: SetEvent(exitEvent);
321: Sleep( 100 ); //##++
322: }
323: break;
324:
325: default :
326: /* pass to next handler */
327: return FALSE;
328: }
329:
330: /* we've handled it, no more handlers should be called */
331: return TRUE;
332: }
333:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>