Annotation of embedaddon/ntp/ports/winnt/ntpd/ntservice.c, revision 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>