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>