Annotation of sbbs/src/sbbs3/ntsvcs.c, revision 1.1

1.1     ! root        1: /* ntsvcs.c */
        !             2: 
        !             3: /* Synchronet BBS as a set of Windows NT Services */
        !             4: 
        !             5: /* $Id: ntsvcs.c,v 1.35 2006/12/31 00:07:50 rswindell Exp $ */
        !             6: 
        !             7: /****************************************************************************
        !             8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
        !             9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
        !            10:  *                                                                                                                                                     *
        !            11:  * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html         *
        !            12:  *                                                                                                                                                     *
        !            13:  * This program is free software; you can redistribute it and/or                       *
        !            14:  * modify it under the terms of the GNU General Public License                         *
        !            15:  * as published by the Free Software Foundation; either version 2                      *
        !            16:  * of the License, or (at your option) any later version.                                      *
        !            17:  * See the GNU General Public License for more details: gpl.txt or                     *
        !            18:  * http://www.fsf.org/copyleft/gpl.html                                                                                *
        !            19:  *                                                                                                                                                     *
        !            20:  * Anonymous FTP access to the most recent released source is available at     *
        !            21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
        !            22:  *                                                                                                                                                     *
        !            23:  * Anonymous CVS access to the development source and modification history     *
        !            24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
        !            25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
        !            26:  *     (just hit return, no password is necessary)                                                     *
        !            27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
        !            28:  *                                                                                                                                                     *
        !            29:  * For Synchronet coding style and modification guidelines, see                                *
        !            30:  * http://www.synchro.net/source.html                                                                          *
        !            31:  *                                                                                                                                                     *
        !            32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
        !            33:  * format) via e-mail to [email protected]                                                                      *
        !            34:  *                                                                                                                                                     *
        !            35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
        !            36:  ****************************************************************************/
        !            37: 
        !            38: /* Synchronet-specific headers */
        !            39: #include "sbbs.h"              /* various */
        !            40: #include "sbbs_ini.h"  /* sbbs_read_ini() */
        !            41: #include "ftpsrvr.h"   /* ftp_startup_t, ftp_server */
        !            42: #include "websrvr.h"   /* web_startup_t, web_server */
        !            43: #include "mailsrvr.h"  /* mail_startup_t, mail_server */
        !            44: #include "services.h"  /* services_startup_t, services_thread */
        !            45: #include "ntsvcs.h"            /* NT service names */
        !            46: 
        !            47: /* Windows-specific headers */
        !            48: #include <winsvc.h>
        !            49: 
        !            50: #define NTSVC_TIMEOUT_STARTUP  30000   /* Milliseconds */
        !            51: #define NTSVC_TIMEOUT_TERMINATE        30000   /* Milliseconds */
        !            52: 
        !            53: #define STRLEN_MAX_DISPLAY_NAME        35
        !            54: 
        !            55: #define STRLEN_SYNCHRONET              10              /* this number ain't change'n */
        !            56: 
        !            57: #define SERVICE_NOT_INSTALLED  (SERVICE_DISABLED+1)
        !            58: 
        !            59: static void WINAPI bbs_ctrl_handler(DWORD dwCtrlCode);
        !            60: static void WINAPI ftp_ctrl_handler(DWORD dwCtrlCode);
        !            61: static void WINAPI web_ctrl_handler(DWORD dwCtrlCode);
        !            62: static void WINAPI mail_ctrl_handler(DWORD dwCtrlCode);
        !            63: static void WINAPI services_ctrl_handler(DWORD dwCtrlCode);
        !            64: 
        !            65: /* Global variables */
        !            66: 
        !            67: char                           ini_file[MAX_PATH+1];
        !            68: bbs_startup_t          bbs_startup;
        !            69: ftp_startup_t          ftp_startup;
        !            70: mail_startup_t         mail_startup;
        !            71: services_startup_t     services_startup;
        !            72: web_startup_t          web_startup;
        !            73: 
        !            74: typedef struct {
        !            75:        char*                                   name;
        !            76:        char*                                   display_name;
        !            77:        char*                                   description;
        !            78:        void*                                   startup;
        !            79:        DWORD*                                  options;
        !            80:        BOOL*                                   recycle_now;
        !            81:        int*                                    log_level;
        !            82:        void DLLCALL                    (*thread)(void* arg);
        !            83:        void DLLCALL                    (*terminate)(void);
        !            84:        void                                    (WINAPI *ctrl_handler)(DWORD);
        !            85:        HANDLE                                  log_handle;
        !            86:        HANDLE                                  event_handle;
        !            87:        BOOL                                    autostart;
        !            88:        BOOL                                    debug;
        !            89:        SERVICE_STATUS                  status;
        !            90:        SERVICE_STATUS_HANDLE   status_handle;
        !            91: } sbbs_ntsvc_t;
        !            92: 
        !            93: sbbs_ntsvc_t bbs ={    
        !            94:        NTSVC_NAME_BBS,
        !            95:        "Synchronet Telnet/RLogin/SSH Server",
        !            96:        "Provides support for Telnet, RLogin, and SSH clients and executes timed events. " \
        !            97:                "This service provides the critical functions of your Synchronet BBS.",
        !            98:        &bbs_startup,
        !            99:        &bbs_startup.options,
        !           100:        &bbs_startup.recycle_now,
        !           101:        &bbs_startup.log_level,
        !           102:        bbs_thread,
        !           103:        bbs_terminate,
        !           104:        bbs_ctrl_handler,
        !           105:        INVALID_HANDLE_VALUE
        !           106: };
        !           107: 
        !           108: /* This is not (currently) a separate service, use this for logging only */
        !           109: sbbs_ntsvc_t event ={  
        !           110:        NTSVC_NAME_EVENT,
        !           111:        NULL,
        !           112:        NULL,
        !           113:        NULL,
        !           114:        NULL,
        !           115:        NULL,
        !           116:        &bbs_startup.log_level,
        !           117:        NULL,
        !           118:        NULL,
        !           119:        NULL,
        !           120:        INVALID_HANDLE_VALUE
        !           121: };
        !           122: 
        !           123: sbbs_ntsvc_t ftp = {
        !           124:        NTSVC_NAME_FTP,
        !           125:        "Synchronet FTP Server",
        !           126:        "Provides support for FTP clients (including web browsers) for file transfers.",
        !           127:        &ftp_startup,
        !           128:        &ftp_startup.options,
        !           129:        &ftp_startup.recycle_now,
        !           130:        &ftp_startup.log_level,
        !           131:        ftp_server,
        !           132:        ftp_terminate,
        !           133:        ftp_ctrl_handler,
        !           134:        INVALID_HANDLE_VALUE
        !           135: };
        !           136: 
        !           137: sbbs_ntsvc_t web = {
        !           138:        NTSVC_NAME_WEB,
        !           139:        "Synchronet Web Server",
        !           140:        "Provides support for Web (HTML/HTTP) clients (browsers).",
        !           141:        &web_startup,
        !           142:        &web_startup.options,
        !           143:        &web_startup.recycle_now,
        !           144:        &web_startup.log_level,
        !           145:        web_server,
        !           146:        web_terminate,
        !           147:        web_ctrl_handler,
        !           148:        INVALID_HANDLE_VALUE
        !           149: };
        !           150: 
        !           151: sbbs_ntsvc_t mail = {
        !           152:        NTSVC_NAME_MAIL,
        !           153:        "Synchronet SMTP/POP3 Mail Server",
        !           154:        "Sends and receives Internet e-mail (using SMTP) and allows users to remotely " \
        !           155:                "access their e-mail using an Internet mail client (using POP3).",
        !           156:        &mail_startup,
        !           157:        &mail_startup.options,
        !           158:        &mail_startup.recycle_now,
        !           159:        &mail_startup.log_level,
        !           160:        mail_server,
        !           161:        mail_terminate,
        !           162:        mail_ctrl_handler,
        !           163:        INVALID_HANDLE_VALUE
        !           164: };
        !           165: 
        !           166: sbbs_ntsvc_t services = {
        !           167:        NTSVC_NAME_SERVICES,
        !           168:        "Synchronet Services",
        !           169:        "Plugin servers (usually in JavaScript) for any TCP/UDP protocol. " \
        !           170:                "Stock services include Finger, Gopher, NNTP, and IRC. Edit your ctrl/services.ini " \
        !           171:                "file for configuration of individual Synchronet Services.",
        !           172:        &services_startup,
        !           173:        &services_startup.options,
        !           174:        &services_startup.recycle_now,
        !           175:        &services_startup.log_level,
        !           176:        services_thread,
        !           177:        services_terminate,
        !           178:        services_ctrl_handler,
        !           179:        INVALID_HANDLE_VALUE
        !           180: };
        !           181: 
        !           182: /* This list is used for enumerating all services */
        !           183: sbbs_ntsvc_t* ntsvc_list[] = {
        !           184:        &bbs,
        !           185:        &ftp,
        !           186:        &web,
        !           187:        &mail,
        !           188:        &services,
        !           189:        NULL
        !           190: };
        !           191:                                                        
        !           192: /****************************************/
        !           193: /* Service Control Handlers (Callbacks) */
        !           194: /****************************************/
        !           195: 
        !           196: /* Common control handler for all services */
        !           197: static void svc_ctrl_handler(sbbs_ntsvc_t* svc, DWORD dwCtrlCode)
        !           198: {
        !           199:        switch(dwCtrlCode) {
        !           200:                case SERVICE_CONTROL_RECYCLE:
        !           201:                        *svc->recycle_now=TRUE;
        !           202:                        break;
        !           203:                case SERVICE_CONTROL_MUTE:
        !           204:                        *svc->options|=BBS_OPT_MUTE;
        !           205:                        break;
        !           206:                case SERVICE_CONTROL_UNMUTE:
        !           207:                        *svc->options&=~BBS_OPT_MUTE;
        !           208:                        break;
        !           209:                case SERVICE_CONTROL_STOP:
        !           210:                case SERVICE_CONTROL_SHUTDOWN:
        !           211:                        svc->terminate();
        !           212:                        svc->status.dwWaitHint=NTSVC_TIMEOUT_TERMINATE;
        !           213:                        svc->status.dwCurrentState=SERVICE_STOP_PENDING;
        !           214:                        break;
        !           215:        }
        !           216:        SetServiceStatus(svc->status_handle, &svc->status);
        !           217: }
        !           218: 
        !           219: /* Service-specific control handler stub functions */
        !           220: static void WINAPI bbs_ctrl_handler(DWORD dwCtrlCode)
        !           221: {
        !           222:        switch(dwCtrlCode) {
        !           223:                case SERVICE_CONTROL_SYSOP_AVAILABLE:
        !           224:                        bbs_startup.options|=BBS_OPT_SYSOP_AVAILABLE;
        !           225:                        break;
        !           226:                case SERVICE_CONTROL_SYSOP_UNAVAILABLE:
        !           227:                        bbs_startup.options&=~BBS_OPT_SYSOP_AVAILABLE;
        !           228:                        break;
        !           229:                default:
        !           230:                        svc_ctrl_handler(&bbs, dwCtrlCode);
        !           231:                        break;
        !           232:        }
        !           233: }
        !           234: 
        !           235: static void WINAPI ftp_ctrl_handler(DWORD dwCtrlCode)
        !           236: {
        !           237:        svc_ctrl_handler(&ftp, dwCtrlCode);
        !           238: }
        !           239: 
        !           240: static void WINAPI web_ctrl_handler(DWORD dwCtrlCode)
        !           241: {
        !           242:        svc_ctrl_handler(&web, dwCtrlCode);
        !           243: }
        !           244: 
        !           245: static void WINAPI mail_ctrl_handler(DWORD dwCtrlCode)
        !           246: {
        !           247:        svc_ctrl_handler(&mail, dwCtrlCode);
        !           248: }
        !           249: 
        !           250: static void WINAPI services_ctrl_handler(DWORD dwCtrlCode)
        !           251: {
        !           252:        svc_ctrl_handler(&services, dwCtrlCode);
        !           253: }
        !           254: 
        !           255: static WORD event_type(int level)
        !           256: {
        !           257:        switch(level) {
        !           258:                case LOG_WARNING:
        !           259:                        return(EVENTLOG_WARNING_TYPE);
        !           260:                case LOG_NOTICE:
        !           261:                case LOG_INFO:
        !           262:                case LOG_DEBUG:
        !           263:                        return(EVENTLOG_INFORMATION_TYPE);      /* same as EVENT_LOG_SUCCESS */
        !           264:        }
        !           265: /*
        !           266:        LOG_EMERG
        !           267:        LOG_ALERT
        !           268:        LOG_CRIT
        !           269:        LOG_ERR
        !           270: */
        !           271:        return(EVENTLOG_ERROR_TYPE);
        !           272: }
        !           273: 
        !           274: /**************************************/
        !           275: /* Common Service Log Ouptut Function */
        !           276: /**************************************/
        !           277: static int svc_lputs(void* p, int level, char* str)
        !           278: {
        !           279:        char    debug[1024];
        !           280:        char    fname[256];
        !           281:        DWORD   len;
        !           282:        DWORD   wr;
        !           283:        sbbs_ntsvc_t* svc = (sbbs_ntsvc_t*)p;
        !           284: 
        !           285:        /* Debug Logging */
        !           286:        if(svc==NULL || svc->debug) {
        !           287:                snprintf(debug,sizeof(debug),"%s: %s",svc==NULL ? "Synchronet" : svc->name, str);
        !           288:                OutputDebugString(debug);
        !           289:        }
        !           290:        if(svc==NULL)
        !           291:                return(0);
        !           292: 
        !           293:        len = strlen(str);
        !           294: 
        !           295:        /* Mailslot Logging (for sbbsctrl) */
        !           296:        if(svc->log_handle != INVALID_HANDLE_VALUE /* Invalid log handle? */
        !           297:                && !GetMailslotInfo(svc->log_handle, NULL, NULL, NULL, NULL)) {
        !           298:                /* Close and try to re-open */
        !           299:                CloseHandle(svc->log_handle);
        !           300:                svc->log_handle=INVALID_HANDLE_VALUE;
        !           301:        }
        !           302: 
        !           303:        if(svc->log_handle == INVALID_HANDLE_VALUE) {
        !           304:                sprintf(fname,"\\\\.\\mailslot\\%s.log",svc->name);
        !           305:                svc->log_handle = CreateFile(
        !           306:                        fname,                                  /* pointer to name of the file */
        !           307:                        GENERIC_WRITE,                  /* access (read-write) mode */
        !           308:                        FILE_SHARE_READ,                /* share mode */
        !           309:                        NULL,                                   /* pointer to security attributes */
        !           310:                        OPEN_EXISTING,                  /* how to create */
        !           311:                        FILE_ATTRIBUTE_NORMAL,  /* file attributes */
        !           312:                        NULL                                    /* handle to file with attributes to copy */
        !           313:                        );
        !           314:        }
        !           315:        if(svc->log_handle != INVALID_HANDLE_VALUE) {
        !           316:                if(!WriteFile(svc->log_handle,str,len,&wr,NULL) || wr!=len) {
        !           317:                        /* This most likely indicates the server closed the mailslot */
        !           318:                        sprintf(debug,"!ERROR %d writing %u bytes to %s pipe (wr=%d)"
        !           319:                                ,GetLastError(),len,svc->name,wr);
        !           320:                        OutputDebugString(debug);
        !           321:                        /* So close the handle and attempt re-open next time */
        !           322:                        CloseHandle(svc->log_handle);
        !           323:                        svc->log_handle=INVALID_HANDLE_VALUE;
        !           324:                }
        !           325:        }
        !           326:        
        !           327:        /* Event Logging */
        !           328:        if(level <= (*svc->log_level)) {
        !           329:                if(svc->event_handle == NULL)
        !           330:                        svc->event_handle = RegisterEventSource(
        !           331:                                NULL,           /* server name for source (NULL = local computer) */
        !           332:                                svc->name   /* source name for registered handle */
        !           333:                                );
        !           334:                if(svc->event_handle != NULL)
        !           335:                        ReportEvent(svc->event_handle,  /* event log handle */
        !           336:                                event_type(level),              /* event type */
        !           337:                                0,                                              /* category zero */
        !           338:                                0,                                              /* event identifier */
        !           339:                                NULL,                                   /* no user security identifier */
        !           340:                                1,                                              /* one string */
        !           341:                                0,                                              /* no data */
        !           342:                                (LPCSTR*)&str,                  /* pointer to string array */
        !           343:                                NULL);                                  /* pointer to data */
        !           344:        }
        !           345: 
        !           346:     return(0);
        !           347: }
        !           348: 
        !           349: /****************************************************************************/
        !           350: /* Event thread local/log print routine                                                                                */
        !           351: /****************************************************************************/
        !           352: static int event_lputs(int level, char *str)
        !           353: {
        !           354:        svc_lputs(&event,level,str);
        !           355:     return(0);
        !           356: }
        !           357: 
        !           358: /************************************/
        !           359: /* Shared Service Callback Routines */
        !           360: /************************************/
        !           361: 
        !           362: static void svc_started(void* p)
        !           363: {
        !           364:        sbbs_ntsvc_t* svc = (sbbs_ntsvc_t*)p;
        !           365: 
        !           366:        svc->status.dwCurrentState=SERVICE_RUNNING;
        !           367:        svc->status.dwControlsAccepted|=SERVICE_ACCEPT_STOP;
        !           368:        SetServiceStatus(svc->status_handle, &svc->status);
        !           369: }
        !           370: 
        !           371: static void read_ini(sbbs_ntsvc_t* svc)
        !           372: {
        !           373:        char    str[MAX_PATH*2];
        !           374:        FILE*   fp;
        !           375:        bbs_startup_t*          bbs_startup=NULL;
        !           376:        ftp_startup_t*          ftp_startup=NULL;
        !           377:        mail_startup_t*         mail_startup=NULL;
        !           378:        services_startup_t*     services_startup=NULL;
        !           379:        web_startup_t*          web_startup=NULL;
        !           380: 
        !           381:        if(svc==&bbs)
        !           382:                bbs_startup=svc->startup;
        !           383:        else if(svc==&ftp)
        !           384:                ftp_startup=svc->startup;
        !           385:        else if(svc==&web)
        !           386:                web_startup=svc->startup;
        !           387:        else if(svc==&mail)
        !           388:                mail_startup=svc->startup;
        !           389:        else if(svc==&services)
        !           390:                services_startup=svc->startup;
        !           391: 
        !           392:        if((fp=fopen(ini_file,"r"))!=NULL) {
        !           393:                sprintf(str,"Reading %s",ini_file);
        !           394:                svc_lputs(NULL,LOG_INFO,str);
        !           395:        }
        !           396: 
        !           397:        /* We call this function to set defaults, even if there's no .ini file */
        !           398:        sbbs_read_ini(fp 
        !           399:                ,NULL   /* global_startup */
        !           400:                ,NULL   ,bbs_startup
        !           401:                ,NULL   ,ftp_startup 
        !           402:                ,NULL   ,web_startup
        !           403:                ,NULL   ,mail_startup 
        !           404:                ,NULL   ,services_startup
        !           405:                );
        !           406: 
        !           407:        /* close .ini file here */
        !           408:        if(fp!=NULL)
        !           409:                fclose(fp);
        !           410: }
        !           411: 
        !           412: static void svc_recycle(void *p)
        !           413: {
        !           414:        read_ini((sbbs_ntsvc_t*)p);
        !           415: }
        !           416: 
        !           417: static void svc_terminated(void* p, int code)
        !           418: {
        !           419:        sbbs_ntsvc_t* svc = (sbbs_ntsvc_t*)p;
        !           420: 
        !           421:        if(code) {
        !           422:                svc->status.dwWin32ExitCode=ERROR_SERVICE_SPECIFIC_ERROR;
        !           423:                svc->status.dwServiceSpecificExitCode=code;
        !           424:                SetServiceStatus(svc->status_handle, &svc->status);
        !           425:        }
        !           426: }
        !           427: 
        !           428: static void svc_clients(void* p, int active)
        !           429: {
        !           430:        sbbs_ntsvc_t* svc = (sbbs_ntsvc_t*)p;
        !           431: }
        !           432: 
        !           433: /***************/
        !           434: /* ServiceMain */
        !           435: /***************/
        !           436: 
        !           437: /* Common ServiceMain for all services */
        !           438: static void WINAPI svc_main(sbbs_ntsvc_t* svc, DWORD argc, LPTSTR *argv)
        !           439: {
        !           440:        char    str[256];
        !           441:        DWORD   i;
        !           442:        char*   arg;
        !           443: 
        !           444:        for(i=0;i<argc;i++) {
        !           445:                arg=argv[i];
        !           446:                if(*arg=='-' || *arg=='/')
        !           447:                        arg++;
        !           448:                if(!stricmp(arg,"debug"))
        !           449:                        svc->debug=TRUE;
        !           450:                if(!stricmp(arg,"loglevel") && i+1<argc)
        !           451:                        (*svc->log_level)=strtol(argv[++i],NULL,0);
        !           452:        }
        !           453: 
        !           454:        sprintf(str,"Starting NT Service: %s",svc->display_name);
        !           455:        svc_lputs(svc,LOG_INFO,str);
        !           456: 
        !           457:     if((svc->status_handle = RegisterServiceCtrlHandler(svc->name, svc->ctrl_handler))==0) {
        !           458:                sprintf(str,"!ERROR %d registering service control handler",GetLastError());
        !           459:                svc_lputs(NULL,LOG_ERR,str);
        !           460:                return;
        !           461:        }
        !           462: 
        !           463:        memset(&svc->status,0,sizeof(SERVICE_STATUS));
        !           464:        svc->status.dwServiceType=SERVICE_WIN32_SHARE_PROCESS;
        !           465:        svc->status.dwControlsAccepted=SERVICE_ACCEPT_SHUTDOWN;
        !           466:        svc->status.dwWaitHint=NTSVC_TIMEOUT_STARTUP;
        !           467: 
        !           468:        svc->status.dwCurrentState=SERVICE_START_PENDING;
        !           469:        SetServiceStatus(svc->status_handle, &svc->status);
        !           470: 
        !           471:        read_ini(svc);
        !           472: 
        !           473:        svc->thread(svc->startup);
        !           474: 
        !           475:        svc->status.dwCurrentState=SERVICE_STOPPED;
        !           476:        SetServiceStatus(svc->status_handle, &svc->status);
        !           477: 
        !           478:        if(svc->log_handle!=INVALID_HANDLE_VALUE) {
        !           479:                CloseHandle(svc->log_handle);
        !           480:                svc->log_handle=INVALID_HANDLE_VALUE;
        !           481:        }
        !           482: 
        !           483:        if(svc->event_handle!=NULL) {
        !           484:                DeregisterEventSource(svc->event_handle);
        !           485:                svc->event_handle=NULL;
        !           486:        }
        !           487: }
        !           488: 
        !           489: /* Service-specific ServiceMain stub functions */
        !           490: 
        !           491: static void WINAPI bbs_start(DWORD dwArgc, LPTSTR *lpszArgv)
        !           492: {
        !           493:        svc_main(&bbs, dwArgc, lpszArgv);
        !           494: 
        !           495:        /* Events are (currently) part of the BBS service */
        !           496:        if(event.log_handle!=INVALID_HANDLE_VALUE) {
        !           497:                CloseHandle(event.log_handle);
        !           498:                event.log_handle=INVALID_HANDLE_VALUE;
        !           499:        }
        !           500: }
        !           501: 
        !           502: static void WINAPI ftp_start(DWORD dwArgc, LPTSTR *lpszArgv)
        !           503: {
        !           504:        svc_main(&ftp, dwArgc, lpszArgv);
        !           505: }
        !           506: 
        !           507: static void WINAPI web_start(DWORD dwArgc, LPTSTR *lpszArgv)
        !           508: {
        !           509:        svc_main(&web, dwArgc, lpszArgv);
        !           510: }
        !           511: 
        !           512: static void WINAPI mail_start(DWORD dwArgc, LPTSTR *lpszArgv)
        !           513: {
        !           514:        svc_main(&mail, dwArgc, lpszArgv);
        !           515: }
        !           516: 
        !           517: static void WINAPI services_start(DWORD dwArgc, LPTSTR *lpszArgv)
        !           518: {
        !           519:        svc_main(&services, dwArgc, lpszArgv);
        !           520: }
        !           521: 
        !           522: /******************************************/
        !           523: /* NT Serivce Install/Uninstall Functions */
        !           524: /******************************************/
        !           525: 
        !           526: /* ChangeServiceConfig2 is a Win2K+ API function, must call dynamically */
        !           527: typedef WINADVAPI BOOL (WINAPI *ChangeServiceConfig2_t)(SC_HANDLE, DWORD, LPCVOID);
        !           528: 
        !           529: static void describe_service(HANDLE hSCMlib, SC_HANDLE hService, char* description)
        !           530: {
        !           531:        ChangeServiceConfig2_t changeServiceConfig2;
        !           532:        static SERVICE_DESCRIPTION service_desc;
        !           533:   
        !           534:        if(hSCMlib==NULL)
        !           535:                return;
        !           536: 
        !           537:        service_desc.lpDescription=description;
        !           538: 
        !           539:        if((changeServiceConfig2 = (ChangeServiceConfig2_t)GetProcAddress(hSCMlib, "ChangeServiceConfig2A"))!=NULL)
        !           540:                changeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &service_desc);
        !           541: }
        !           542: 
        !           543: static BOOL register_event_source(char* name, char* path)
        !           544: {
        !           545:        char    keyname[256];
        !           546:        HKEY    hKey;
        !           547:        DWORD   type;
        !           548:        DWORD   disp;
        !           549:        LONG    retval;
        !           550:        char*   value;
        !           551: 
        !           552:        sprintf(keyname,"system\\CurrentControlSet\\services\\eventlog\\application\\%s",name);
        !           553: 
        !           554:        retval=RegCreateKeyEx(
        !           555:                HKEY_LOCAL_MACHINE,                     /* handle to an open key */
        !           556:                keyname,                        /* address of subkey name */
        !           557:                0,                              /* reserved */
        !           558:                "",                             /* address of class string */
        !           559:                0,                              /* special options flag */
        !           560:                KEY_ALL_ACCESS, /* desired security access */
        !           561:                NULL,           /* address of key security structure */
        !           562:                &hKey,                  /* address of buffer for opened handle */
        !           563:                &disp                   /* address of disposition value buffer */
        !           564:                );
        !           565: 
        !           566:        if(retval!=ERROR_SUCCESS) {
        !           567:                fprintf(stderr,"!Error %d creating/opening registry key (HKLM\\%s)\n"
        !           568:                        ,retval,keyname);
        !           569:                return(FALSE);
        !           570:        }
        !           571: 
        !           572:        value="EventMessageFile";
        !           573:        retval=RegSetValueEx(
        !           574:                hKey,                   /* handle to key to set value for */
        !           575:                value,                  /* name of the value to set */
        !           576:                0,                              /* reserved */
        !           577:                REG_SZ,                 /* flag for value type */
        !           578:                path,                   /* address of value data */
        !           579:                strlen(path)    /* size of value data */
        !           580:                );
        !           581: 
        !           582:        if(retval!=ERROR_SUCCESS) {
        !           583:                RegCloseKey(hKey);
        !           584:                fprintf(stderr,"!Error %d setting registry key value (%s)\n"
        !           585:                        ,retval,value);
        !           586:                return(FALSE);
        !           587:        }
        !           588: 
        !           589:        value="TypesSupported";
        !           590:        type=EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
        !           591:        retval=RegSetValueEx(
        !           592:                hKey,                   /* handle to key to set value for */
        !           593:                value,                  /* name of the value to set */
        !           594:                0,                              /* reserved */
        !           595:                REG_DWORD,              /* flag for value type */
        !           596:                (BYTE*)&type,   /* address of value data */
        !           597:                sizeof(type)    /* size of value data */
        !           598:                );
        !           599: 
        !           600:        RegCloseKey(hKey);
        !           601: 
        !           602:        if(retval!=ERROR_SUCCESS) {
        !           603:                fprintf(stderr,"!Error %d setting registry key value (%s)\n"
        !           604:                        ,retval,value);
        !           605:                return(FALSE);
        !           606:        }
        !           607: 
        !           608:        return(TRUE);
        !           609: }
        !           610: 
        !           611: static const char* start_type_desc(DWORD start_type)
        !           612: {
        !           613:        static char str[128];
        !           614: 
        !           615:        switch(start_type) {
        !           616:                case SERVICE_AUTO_START:                        return("Startup: Automatic");
        !           617:                case SERVICE_DEMAND_START:                      return("Startup: Manual");
        !           618:                case SERVICE_DISABLED:                          return("Disabled");
        !           619:                case SERVICE_NOT_INSTALLED:                     return("Not installed");
        !           620:        }
        !           621: 
        !           622:        sprintf(str,"Start_type: %d", start_type);
        !           623:        return(str);
        !           624: }
        !           625: 
        !           626: static const char* state_desc(DWORD state)
        !           627: {
        !           628:        static char str[128];
        !           629: 
        !           630:        switch(state) {
        !           631:                case SERVICE_STOPPED:                           return("Stopped");
        !           632:                case SERVICE_START_PENDING:                     return("Start Pending");
        !           633:                case SERVICE_STOP_PENDING:                      return("Stop Pending");
        !           634:                case SERVICE_RUNNING:                           return("Running");
        !           635:                case SERVICE_CONTINUE_PENDING:          return("Continue Pending");
        !           636:                case SERVICE_PAUSE_PENDING:                     return("Pause Pending");
        !           637:                case SERVICE_PAUSED:                            return("Paused");
        !           638:        }
        !           639: 
        !           640:        sprintf(str,"State: %d", state);
        !           641:        return(str);
        !           642: }
        !           643: 
        !           644: static const char* control_desc(DWORD ctrl)
        !           645: {
        !           646:        static char str[128];
        !           647: 
        !           648:        switch(ctrl) {
        !           649:                case SERVICE_CONTROL_STOP:
        !           650:                        return("Stopping");
        !           651:                case SERVICE_CONTROL_PAUSE:
        !           652:                        return("Pausing");
        !           653:                case SERVICE_CONTROL_CONTINUE:
        !           654:                        return("Continuing");
        !           655:                case SERVICE_CONTROL_INTERROGATE:
        !           656:                        return("Interrogating");
        !           657:                case SERVICE_CONTROL_SHUTDOWN:
        !           658:                        return("Shutting-down");
        !           659: 
        !           660:                /* Synchronet-specific */
        !           661:                case SERVICE_CONTROL_RECYCLE:
        !           662:                        return("Recycling");
        !           663:                case SERVICE_CONTROL_MUTE:
        !           664:                        return("Muting");
        !           665:                case SERVICE_CONTROL_UNMUTE:
        !           666:                        return("Un-muting");
        !           667:                case SERVICE_CONTROL_SYSOP_AVAILABLE:
        !           668:                        return("Sysop Available");
        !           669:                case SERVICE_CONTROL_SYSOP_UNAVAILABLE: 
        !           670:                        return("Sysop Unavailable");
        !           671:        }
        !           672:        sprintf(str,"Control: %d", ctrl);
        !           673:        return(str);
        !           674: }
        !           675: 
        !           676: /****************************************************************************/
        !           677: /* Utility function to detect if a service is currently disabled                       */
        !           678: /****************************************************************************/
        !           679: static DWORD get_service_info(SC_HANDLE hSCManager, char* name, DWORD* state)
        !           680: {
        !           681:     SC_HANDLE          hService;
        !           682:        DWORD                   size;
        !           683:        DWORD                   err;
        !           684:        SERVICE_STATUS  status;
        !           685:        LPQUERY_SERVICE_CONFIG service_config;
        !           686: 
        !           687:        if(state!=NULL)
        !           688:                *state=SERVICE_STOPPED;
        !           689: 
        !           690:        if((hService = OpenService(hSCManager, name, SERVICE_ALL_ACCESS))==NULL) {
        !           691:                if((err=GetLastError())==ERROR_SERVICE_DOES_NOT_EXIST)
        !           692:                        return(SERVICE_NOT_INSTALLED);
        !           693:                printf("\n!ERROR %d opening service: %s\n",err,name);
        !           694:                return(-1);
        !           695:        }
        !           696: 
        !           697:        if(QueryServiceConfig(
        !           698:                hService,               /* handle of service */
        !           699:                NULL,                   /* address of service config. structure */
        !           700:                0,                              /* size of service configuration buffer */
        !           701:                &size                   /* address of variable for bytes needed */
        !           702:                ) || GetLastError()!=ERROR_INSUFFICIENT_BUFFER) {
        !           703:                printf("\n!Unexpected QueryServiceConfig ERROR %u\n",err=GetLastError());
        !           704:                return(-1);
        !           705:        }
        !           706: 
        !           707:        if(state!=NULL && QueryServiceStatus(hService,&status))
        !           708:                *state=status.dwCurrentState;
        !           709: 
        !           710:        if((service_config=alloca(size))==NULL) {
        !           711:                printf("\n!ERROR allocating %u bytes of memory\n", size);
        !           712:                return(-1);
        !           713:        }
        !           714: 
        !           715:        if(!QueryServiceConfig(
        !           716:                hService,               /* handle of service */
        !           717:                service_config, /* address of service config. structure */
        !           718:                size,                   /* size of service configuration buffer */
        !           719:                &size                   /* address of variable for bytes needed */
        !           720:                )) {
        !           721:                printf("\n!QueryServiceConfig ERROR %u\n",GetLastError());
        !           722:                return(-1);
        !           723:        }
        !           724:     CloseServiceHandle(hService);
        !           725: 
        !           726:        return(service_config->dwStartType);
        !           727: }
        !           728: 
        !           729: /****************************************************************************/
        !           730: /* Utility function to create a service with description (on Win2K+)           */
        !           731: /****************************************************************************/
        !           732: static SC_HANDLE create_service(HANDLE hSCMlib, SC_HANDLE hSCManager
        !           733:                                                                ,char* name, char* display_name, char* description, char* path
        !           734:                                                                ,BOOL autostart)
        !           735: {
        !           736:     SC_HANDLE   hService;
        !           737:        DWORD           err;
        !           738:        DWORD           start_type = autostart ? SERVICE_AUTO_START : SERVICE_DEMAND_START;
        !           739: 
        !           740:        printf("Installing service: %-*s ... ", STRLEN_MAX_DISPLAY_NAME, display_name);
        !           741: 
        !           742:     hService = CreateService(
        !           743:         hSCManager,                                            /* SCManager database */
        !           744:         name,                                                  /* name of service */
        !           745:         display_name,                                  /* name to display */
        !           746:         SERVICE_ALL_ACCESS,                            /* desired access */
        !           747:         SERVICE_WIN32_SHARE_PROCESS,   /* service type */
        !           748:                start_type,                                             /* start type (auto or manual) */
        !           749:         SERVICE_ERROR_NORMAL,                  /* error control type */
        !           750:         path,                                                  /* service's binary */
        !           751:         NULL,                                                  /* no load ordering group */
        !           752:         NULL,                                                  /* no tag identifier */
        !           753:         "",                                                            /* dependencies */
        !           754:         NULL,                                                  /* LocalSystem account */
        !           755:         NULL);                                                 /* no password */
        !           756: 
        !           757:        if(hService==NULL) {
        !           758:                if((err=GetLastError())==ERROR_SERVICE_EXISTS)
        !           759:                        printf("Already installed\n");
        !           760:                else
        !           761:                        printf("!ERROR %d\n",err);
        !           762:        }
        !           763:        else {
        !           764:                describe_service(hSCMlib, hService,description);
        !           765:                CloseServiceHandle(hService);
        !           766:                printf("%s\n", start_type_desc(start_type));
        !           767: 
        !           768:                register_event_source(name,path);
        !           769:                register_event_source(NTSVC_NAME_EVENT,path);   /* Create SynchronetEvent event source */
        !           770:        }
        !           771: 
        !           772:        return(hService);
        !           773: }
        !           774: 
        !           775: /****************************************************************************/
        !           776: /* Install one or all services                                                                                         */
        !           777: /****************************************************************************/
        !           778: static int install(const char* svc_name)
        !           779: {
        !           780:        int                     i;
        !           781:        HANDLE          hSCMlib;
        !           782:     SC_HANDLE   hSCManager;
        !           783:     char               path[MAX_PATH+1];
        !           784: 
        !           785:        printf("Installing Synchronet NT Services...\n");
        !           786: 
        !           787:        hSCMlib = LoadLibrary("ADVAPI32.DLL");
        !           788: 
        !           789:     if(GetModuleFileName(NULL,path,sizeof(path))==0)
        !           790:     {
        !           791:         fprintf(stderr,"!ERROR %d getting module file name\n",GetLastError());
        !           792:         return(-1);
        !           793:     }
        !           794: 
        !           795:     hSCManager = OpenSCManager(
        !           796:                         NULL,                   /* machine (NULL == local) */
        !           797:                         NULL,                   /* database (NULL == default) */
        !           798:                         SC_MANAGER_ALL_ACCESS   /* access required */
        !           799:                         );
        !           800:     if(hSCManager==NULL) {
        !           801:                fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError());
        !           802:                return(-1);
        !           803:        }
        !           804: 
        !           805:        for(i=0;ntsvc_list[i]!=NULL;i++)
        !           806:                if(svc_name==NULL       /* All? */
        !           807:                        || !stricmp(ntsvc_list[i]->name, svc_name)
        !           808:                        || !stricmp(ntsvc_list[i]->name+STRLEN_SYNCHRONET, svc_name))
        !           809:                        create_service(hSCMlib
        !           810:                                ,hSCManager
        !           811:                                ,ntsvc_list[i]->name
        !           812:                                ,ntsvc_list[i]->display_name
        !           813:                                ,ntsvc_list[i]->description
        !           814:                                ,path
        !           815:                                ,ntsvc_list[i]->autostart);
        !           816: 
        !           817:        if(hSCMlib!=NULL)
        !           818:                FreeLibrary(hSCMlib);
        !           819: 
        !           820:        CloseServiceHandle(hSCManager);
        !           821: 
        !           822:        return(0);
        !           823: }
        !           824: 
        !           825: static SC_HANDLE open_service(SC_HANDLE hSCManager, char* name)
        !           826: {
        !           827:        SC_HANDLE       hService;
        !           828:        DWORD           err;
        !           829: 
        !           830:        if((hService = OpenService(hSCManager, name, SERVICE_ALL_ACCESS))==NULL) {
        !           831:                if((err=GetLastError())==ERROR_SERVICE_DOES_NOT_EXIST)
        !           832:                        printf("Not installed\n");
        !           833:                else
        !           834:                        printf("\n!ERROR %d opening service: %s\n",err,name);
        !           835:                return(NULL);
        !           836:        }
        !           837: 
        !           838:        return(hService);
        !           839: }
        !           840: 
        !           841: /****************************************************************************/
        !           842: /* Utility function to remove a service cleanly (stopping if necessary)                */
        !           843: /****************************************************************************/
        !           844: static void remove_service(SC_HANDLE hSCManager, char* name, char* disp_name)
        !           845: {
        !           846:     SC_HANDLE          hService;
        !           847:        SERVICE_STATUS  status;
        !           848: 
        !           849:        printf("Removing: %-*s ... ", STRLEN_MAX_DISPLAY_NAME, disp_name);
        !           850: 
        !           851:     if((hService=open_service(hSCManager, name))==NULL)
        !           852:                return;
        !           853: 
        !           854:     /* try to stop the service */
        !           855:     if(ControlService( hService, SERVICE_CONTROL_STOP, &status))
        !           856:     {
        !           857:         printf("\nStopping: %-*s ... ", STRLEN_MAX_DISPLAY_NAME, disp_name);
        !           858: 
        !           859:         while(QueryServiceStatus(hService, &status) && status.dwCurrentState == SERVICE_STOP_PENDING)
        !           860:                        Sleep(1000);
        !           861: 
        !           862:         if(status.dwCurrentState == SERVICE_STOPPED)
        !           863:             printf("Stopped, ");
        !           864:         else
        !           865:             printf("FAILED!, ");
        !           866:     }
        !           867: 
        !           868:     /* now remove the service */
        !           869:     if(DeleteService(hService))
        !           870:                printf("Removed\n");
        !           871:        else
        !           872:                printf("!ERROR %d\n",GetLastError());
        !           873:     CloseServiceHandle(hService);
        !           874: }
        !           875: 
        !           876: /****************************************************************************/
        !           877: /* Utility function to stop a service                                                                          */
        !           878: /****************************************************************************/
        !           879: static void stop_service(SC_HANDLE hSCManager, char* name, char* disp_name)
        !           880: {
        !           881:     SC_HANDLE          hService;
        !           882:        SERVICE_STATUS  status;
        !           883: 
        !           884:     printf("Stopping service: %-*s ... ", STRLEN_MAX_DISPLAY_NAME, disp_name);
        !           885:     if((hService=open_service(hSCManager, name))==NULL)
        !           886:                return;
        !           887: 
        !           888:     /* try to stop the service */
        !           889:     if(ControlService( hService, SERVICE_CONTROL_STOP, &status))
        !           890:     {
        !           891:         while(QueryServiceStatus(hService, &status) && status.dwCurrentState == SERVICE_STOP_PENDING)
        !           892:                        Sleep(1000);
        !           893: 
        !           894:         if(status.dwCurrentState == SERVICE_STOPPED)
        !           895:             printf("Stopped\n");
        !           896:         else
        !           897:             printf("FAILED!\n");
        !           898:     } else
        !           899:                printf("Already stopped\n");
        !           900: 
        !           901:     CloseServiceHandle(hService);
        !           902: }
        !           903: 
        !           904: /****************************************************************************/
        !           905: /* Utility function to stop a service                                                                          */
        !           906: /****************************************************************************/
        !           907: static void control_service(SC_HANDLE hSCManager, char* name, char* disp_name, DWORD ctrl)
        !           908: {
        !           909:     SC_HANDLE          hService;
        !           910:        SERVICE_STATUS  status;
        !           911:        DWORD                   err;
        !           912: 
        !           913:     printf("%s service: %-*s ... ", control_desc(ctrl), STRLEN_MAX_DISPLAY_NAME, disp_name);
        !           914:     if((hService=open_service(hSCManager, name))==NULL)
        !           915:                return;
        !           916: 
        !           917:     /* try to stop the service */
        !           918:     if(!ControlService( hService, SERVICE_CONTROL_STOP, &status)) {
        !           919:                if((err=GetLastError())==ERROR_SERVICE_NOT_ACTIVE)
        !           920:                        printf("Not active\n");
        !           921:                else
        !           922:                        printf("!ERROR %d\n",err);
        !           923:     } else
        !           924:                printf("Successful\n");
        !           925: 
        !           926:     CloseServiceHandle(hService);
        !           927: }
        !           928: 
        !           929: 
        !           930: 
        !           931: /****************************************************************************/
        !           932: /* Control one or all services                                                                                         */
        !           933: /****************************************************************************/
        !           934: static int control(const char* svc_name, DWORD ctrl)
        !           935: {
        !           936:        int                     i;
        !           937:     SC_HANDLE   hSCManager;
        !           938: 
        !           939:     hSCManager = OpenSCManager(
        !           940:                         NULL,                   /* machine (NULL == local) */
        !           941:                         NULL,                   /* database (NULL == default) */
        !           942:                         SC_MANAGER_ALL_ACCESS   /* access required */
        !           943:                         );
        !           944:     if(hSCManager==NULL) {
        !           945:                fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError());
        !           946:                return(-1);
        !           947:        }
        !           948: 
        !           949:        for(i=0;ntsvc_list[i]!=NULL;i++) {
        !           950: #if 0
        !           951:                if(svc_name==NULL 
        !           952:                        && get_service_info(hSCManager, ntsvc_list[i]->name,NULL)==SERVICE_DISABLED)
        !           953:                        continue;
        !           954: #endif
        !           955:                if(svc_name==NULL       /* All? */
        !           956:                        || !stricmp(ntsvc_list[i]->name, svc_name)
        !           957:                        || !stricmp(ntsvc_list[i]->name+STRLEN_SYNCHRONET, svc_name))
        !           958:                        switch(ctrl) {
        !           959:                                case SERVICE_CONTROL_STOP:
        !           960:                                        stop_service(hSCManager
        !           961:                                                ,ntsvc_list[i]->name
        !           962:                                                ,ntsvc_list[i]->display_name);
        !           963:                                        break;
        !           964:                                default:
        !           965:                                        control_service(hSCManager
        !           966:                                                ,ntsvc_list[i]->name
        !           967:                                                ,ntsvc_list[i]->display_name
        !           968:                                                ,ctrl);
        !           969:                                        break;
        !           970:                }
        !           971:        }
        !           972: 
        !           973:        CloseServiceHandle(hSCManager);
        !           974: 
        !           975:        return(0);
        !           976: }
        !           977: 
        !           978: /****************************************************************************/
        !           979: /* Utility function to start a service                                                                         */
        !           980: /****************************************************************************/
        !           981: static void start_service(SC_HANDLE hSCManager, char* name, char* disp_name
        !           982:                                                  ,int argc, char** argv)
        !           983: {
        !           984:     SC_HANDLE          hService;
        !           985:        SERVICE_STATUS  status;
        !           986: 
        !           987:     printf("Starting service: %-*s ... ", STRLEN_MAX_DISPLAY_NAME, disp_name);
        !           988:     if((hService=open_service(hSCManager, name))==NULL)
        !           989:                return;
        !           990: 
        !           991:        if(QueryServiceStatus(hService, &status) && status.dwCurrentState == SERVICE_RUNNING)
        !           992:                printf("Already running\n");
        !           993:        else {
        !           994:                /* Start the service */
        !           995:                if(StartService(hService, argc, (LPCTSTR*)argv))
        !           996:                {
        !           997:                        while(QueryServiceStatus(hService, &status) && status.dwCurrentState == SERVICE_START_PENDING)
        !           998:                                Sleep(1000);
        !           999: 
        !          1000:                        if(status.dwCurrentState == SERVICE_RUNNING)
        !          1001:                                printf("Started\n");
        !          1002:                        else
        !          1003:                                printf("FAILED!\n");
        !          1004:                } else
        !          1005:                        printf("!ERROR %u\n", GetLastError());
        !          1006:        }
        !          1007: 
        !          1008:     CloseServiceHandle(hService);
        !          1009: }
        !          1010: 
        !          1011: /****************************************************************************/
        !          1012: /* Uninstall one or all services                                                                                       */
        !          1013: /****************************************************************************/
        !          1014: static int uninstall(const char* svc_name)
        !          1015: {
        !          1016:        int                     i;
        !          1017:     SC_HANDLE   hSCManager;
        !          1018: 
        !          1019:     hSCManager = OpenSCManager(
        !          1020:                         NULL,                   /* machine (NULL == local) */
        !          1021:                         NULL,                   /* database (NULL == default) */
        !          1022:                         SC_MANAGER_ALL_ACCESS   /* access required */
        !          1023:                         );
        !          1024:     if(hSCManager==NULL) {
        !          1025:                fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError());
        !          1026:                return(-1);
        !          1027:        }
        !          1028: 
        !          1029:        for(i=0;ntsvc_list[i]!=NULL;i++)
        !          1030:                if(svc_name==NULL       /* All? */
        !          1031:                        || !stricmp(ntsvc_list[i]->name, svc_name)
        !          1032:                        || !stricmp(ntsvc_list[i]->name+STRLEN_SYNCHRONET, svc_name))
        !          1033:                        remove_service(hSCManager
        !          1034:                                ,ntsvc_list[i]->name
        !          1035:                                ,ntsvc_list[i]->display_name);
        !          1036: 
        !          1037:        CloseServiceHandle(hSCManager);
        !          1038: 
        !          1039:        return(0);
        !          1040: }
        !          1041: 
        !          1042: /****************************************************************************/
        !          1043: /* Utility function to disable a service                                                                       */
        !          1044: /****************************************************************************/
        !          1045: static void set_service_start_type(SC_HANDLE hSCManager, char* name
        !          1046:                                                                   ,char* disp_name, DWORD start_type)
        !          1047: {
        !          1048:     SC_HANDLE          hService;
        !          1049: 
        !          1050:        printf("%s service: %-*s ... "
        !          1051:                ,start_type==SERVICE_DISABLED ? "Disabling" : "Enabling"
        !          1052:                ,STRLEN_MAX_DISPLAY_NAME, disp_name);
        !          1053: 
        !          1054:     if((hService=open_service(hSCManager, name))==NULL)
        !          1055:                return;
        !          1056: 
        !          1057:        if(!ChangeServiceConfig(
        !          1058:                hService,                               /* handle to service */
        !          1059:                SERVICE_NO_CHANGE,              /* type of service */
        !          1060:                start_type,                             /* when to start service */
        !          1061:                SERVICE_NO_CHANGE,              /* severity if service fails to start */
        !          1062:                NULL,                                   /* pointer to service binary file name */
        !          1063:                NULL,                                   /* pointer to load ordering group name */
        !          1064:                NULL,                                   /* pointer to variable to get tag identifier */
        !          1065:                NULL,                                   /* pointer to array of dependency names */
        !          1066:                NULL,                                   /* pointer to account name of service */
        !          1067:                NULL,                                   /* pointer to password for service account */
        !          1068:                NULL                                    /* pointer to display name */
        !          1069:                ))
        !          1070:                printf("\n!ERROR %d changing service config for: %s\n",GetLastError(),name);
        !          1071:        else
        !          1072:                printf("%s\n", start_type_desc(start_type));
        !          1073: 
        !          1074:     CloseServiceHandle(hService);
        !          1075: }
        !          1076: 
        !          1077: /****************************************************************************/
        !          1078: /* Enable (set to auto-start) or disable one or all services                           */
        !          1079: /****************************************************************************/
        !          1080: static int enable(const char* svc_name, BOOL enabled)
        !          1081: {
        !          1082:        int                     i;
        !          1083:     SC_HANDLE   hSCManager;
        !          1084: 
        !          1085:     hSCManager = OpenSCManager(
        !          1086:                         NULL,                   /* machine (NULL == local) */
        !          1087:                         NULL,                   /* database (NULL == default) */
        !          1088:                         SC_MANAGER_ALL_ACCESS   /* access required */
        !          1089:                         );
        !          1090:     if(hSCManager==NULL) {
        !          1091:                fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError());
        !          1092:                return(-1);
        !          1093:        }
        !          1094: 
        !          1095:        for(i=0;ntsvc_list[i]!=NULL;i++)
        !          1096:                if(svc_name==NULL       /* All? */
        !          1097:                        || !stricmp(ntsvc_list[i]->name, svc_name)
        !          1098:                        || !stricmp(ntsvc_list[i]->name+STRLEN_SYNCHRONET, svc_name))
        !          1099:                        set_service_start_type(hSCManager
        !          1100:                                ,ntsvc_list[i]->name
        !          1101:                                ,ntsvc_list[i]->display_name
        !          1102:                                ,enabled ? (ntsvc_list[i]->autostart ? SERVICE_AUTO_START : SERVICE_DEMAND_START)
        !          1103:                                        : SERVICE_DISABLED);
        !          1104: 
        !          1105:        CloseServiceHandle(hSCManager);
        !          1106: 
        !          1107:        return(0);
        !          1108: }
        !          1109: 
        !          1110: /****************************************************************************/
        !          1111: /* List one or all services                                                                                                    */
        !          1112: /****************************************************************************/
        !          1113: static int list(const char* svc_name)
        !          1114: {
        !          1115:        int                     i;
        !          1116:     SC_HANDLE   hSCManager;
        !          1117:        DWORD           state;
        !          1118:        DWORD           start_type;
        !          1119: 
        !          1120:     hSCManager = OpenSCManager(
        !          1121:                         NULL,                   /* machine (NULL == local) */
        !          1122:                         NULL,                   /* database (NULL == default) */
        !          1123:                         SC_MANAGER_ALL_ACCESS   /* access required */
        !          1124:                         );
        !          1125:     if(hSCManager==NULL) {
        !          1126:                fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError());
        !          1127:                return(-1);
        !          1128:        }
        !          1129: 
        !          1130:        for(i=0;ntsvc_list[i]!=NULL;i++) {
        !          1131:                if(svc_name==NULL 
        !          1132:                        || !stricmp(ntsvc_list[i]->name, svc_name)
        !          1133:                        || !stricmp(ntsvc_list[i]->name+STRLEN_SYNCHRONET, svc_name)) {
        !          1134:                        start_type = get_service_info(hSCManager, ntsvc_list[i]->name, &state);
        !          1135:                        printf("%-*s ... %s, %s\n"
        !          1136:                                ,STRLEN_MAX_DISPLAY_NAME, ntsvc_list[i]->display_name
        !          1137:                                ,start_type_desc(start_type)
        !          1138:                                ,state_desc(state));
        !          1139:                }
        !          1140:        }
        !          1141: 
        !          1142:        CloseServiceHandle(hSCManager);
        !          1143: 
        !          1144:        return(0);
        !          1145: }
        !          1146: 
        !          1147: /****************************************************************************/
        !          1148: /* Start one or all services                                                                                           */
        !          1149: /****************************************************************************/
        !          1150: static int start(const char* svc_name, int argc, char** argv)
        !          1151: {
        !          1152:        int                     i;
        !          1153:     SC_HANDLE   hSCManager;
        !          1154: 
        !          1155:     hSCManager = OpenSCManager(
        !          1156:                         NULL,                   /* machine (NULL == local) */
        !          1157:                         NULL,                   /* database (NULL == default) */
        !          1158:                         SC_MANAGER_ALL_ACCESS   /* access required */
        !          1159:                         );
        !          1160:     if(hSCManager==NULL) {
        !          1161:                fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError());
        !          1162:                return(-1);
        !          1163:        }
        !          1164: 
        !          1165:        for(i=0;ntsvc_list[i]!=NULL;i++) {
        !          1166:                if(svc_name==NULL 
        !          1167:                        && get_service_info(hSCManager, ntsvc_list[i]->name,NULL)==SERVICE_DISABLED)
        !          1168:                        continue;
        !          1169:                if(svc_name==NULL 
        !          1170:                        || !stricmp(ntsvc_list[i]->name, svc_name)
        !          1171:                        || !stricmp(ntsvc_list[i]->name+STRLEN_SYNCHRONET, svc_name))
        !          1172:                        start_service(hSCManager,ntsvc_list[i]->name,ntsvc_list[i]->display_name
        !          1173:                                ,argc,argv);
        !          1174:        }
        !          1175: 
        !          1176:        CloseServiceHandle(hSCManager);
        !          1177: 
        !          1178:        return(0);
        !          1179: }
        !          1180: 
        !          1181: /****************************************************************************/
        !          1182: /* Main Entry Point                                                                                                                    */
        !          1183: /****************************************************************************/
        !          1184: int main(int argc, char** argv)
        !          1185: {
        !          1186:        char*   ctrl_dir;
        !          1187:        char*   arg;
        !          1188:        char*   p;
        !          1189:        char    str[MAX_PATH+1];
        !          1190:        int             i;
        !          1191:        FILE*   fp=NULL;
        !          1192:        BOOL    start_services=TRUE;
        !          1193: 
        !          1194:        SERVICE_TABLE_ENTRY  ServiceDispatchTable[] = 
        !          1195:     { 
        !          1196:         { NTSVC_NAME_BBS,              bbs_start               }, 
        !          1197:                { NTSVC_NAME_FTP,               ftp_start               },
        !          1198:                { NTSVC_NAME_WEB,               web_start               },
        !          1199:                { NTSVC_NAME_MAIL,              mail_start              },
        !          1200:                { NTSVC_NAME_SERVICES,  services_start  },
        !          1201:         { NULL,                                        NULL                    }       /* Terminator */
        !          1202:     }; 
        !          1203: 
        !          1204:        printf("\nSynchronet NT Services  Version %s%c  %s\n\n"
        !          1205:                ,VERSION,REVISION,COPYRIGHT_NOTICE);
        !          1206: 
        !          1207:        ctrl_dir=getenv("SBBSCTRL");    /* read from environment variable */
        !          1208:        if(ctrl_dir==NULL || ctrl_dir[0]==0) {
        !          1209:                ctrl_dir="\\sbbs\\ctrl";                /* Not set? Use default */
        !          1210:                printf("!SBBSCTRL environment variable not set, using default value: %s\n\n"
        !          1211:                        ,ctrl_dir);
        !          1212:        }
        !          1213: 
        !          1214:        sbbs_get_ini_fname(ini_file, ctrl_dir, NULL /* auto-host_name */);
        !          1215: 
        !          1216:        /* Initialize BBS startup structure */
        !          1217:     memset(&bbs_startup,0,sizeof(bbs_startup));
        !          1218:     bbs_startup.size=sizeof(bbs_startup);
        !          1219:        bbs_startup.cbdata=&bbs;
        !          1220:        bbs_startup.lputs=svc_lputs;
        !          1221:        bbs_startup.event_lputs=event_lputs;
        !          1222:     bbs_startup.started=svc_started;
        !          1223:        bbs_startup.recycle=svc_recycle;
        !          1224:     bbs_startup.terminated=svc_terminated;
        !          1225:        bbs_startup.clients=svc_clients;
        !          1226:     strcpy(bbs_startup.ctrl_dir,ctrl_dir);
        !          1227: 
        !          1228:        /* Initialize FTP startup structure */
        !          1229:     memset(&ftp_startup,0,sizeof(ftp_startup));
        !          1230:        ftp_startup.cbdata=&ftp;
        !          1231:     ftp_startup.size=sizeof(ftp_startup);
        !          1232:        ftp_startup.lputs=svc_lputs;
        !          1233:     ftp_startup.started=svc_started;
        !          1234:        ftp_startup.recycle=svc_recycle;
        !          1235:     ftp_startup.terminated=svc_terminated;
        !          1236:        ftp_startup.clients=svc_clients;
        !          1237:     strcpy(ftp_startup.ctrl_dir,ctrl_dir);
        !          1238: 
        !          1239:        /* Initialize Web Server startup structure */
        !          1240:     memset(&web_startup,0,sizeof(web_startup));
        !          1241:        web_startup.cbdata=&web;
        !          1242:     web_startup.size=sizeof(web_startup);
        !          1243:        web_startup.lputs=svc_lputs;
        !          1244:     web_startup.started=svc_started;
        !          1245:        web_startup.recycle=svc_recycle;
        !          1246:     web_startup.terminated=svc_terminated;
        !          1247:        web_startup.clients=svc_clients;
        !          1248:     strcpy(web_startup.ctrl_dir,ctrl_dir);
        !          1249: 
        !          1250:        /* Initialize Mail Server startup structure */
        !          1251:     memset(&mail_startup,0,sizeof(mail_startup));
        !          1252:        mail_startup.cbdata=&mail;
        !          1253:     mail_startup.size=sizeof(mail_startup);
        !          1254:        mail_startup.lputs=svc_lputs;
        !          1255:     mail_startup.started=svc_started;
        !          1256:        mail_startup.recycle=svc_recycle;
        !          1257:     mail_startup.terminated=svc_terminated;
        !          1258:        mail_startup.clients=svc_clients;
        !          1259:     strcpy(mail_startup.ctrl_dir,ctrl_dir);
        !          1260: 
        !          1261:        /* Initialize Services startup structure */
        !          1262:     memset(&services_startup,0,sizeof(services_startup));
        !          1263:        services_startup.cbdata=&services;
        !          1264:     services_startup.size=sizeof(services_startup);
        !          1265:        services_startup.lputs=svc_lputs;
        !          1266:     services_startup.started=svc_started;
        !          1267:        services_startup.recycle=svc_recycle;
        !          1268:     services_startup.terminated=svc_terminated;
        !          1269:        services_startup.clients=svc_clients;
        !          1270:     strcpy(services_startup.ctrl_dir,ctrl_dir);
        !          1271: 
        !          1272:        /* Read .ini file here */
        !          1273:        if((fp=fopen(ini_file,"r"))!=NULL) {
        !          1274:                sprintf(str,"Reading %s",ini_file);
        !          1275:                svc_lputs(NULL,LOG_INFO,str);
        !          1276:        }
        !          1277: 
        !          1278:        /* We call this function to set defaults, even if there's no .ini file */
        !          1279:        sbbs_read_ini(fp 
        !          1280:                ,NULL   /* global_startup */
        !          1281:                ,&bbs.autostart                 ,NULL
        !          1282:                ,&ftp.autostart                 ,NULL
        !          1283:                ,&web.autostart                 ,NULL
        !          1284:                ,&mail.autostart                ,NULL
        !          1285:                ,&services.autostart    ,NULL
        !          1286:                );
        !          1287: 
        !          1288:        /* close .ini file here */
        !          1289:        if(fp!=NULL)
        !          1290:                fclose(fp);
        !          1291: 
        !          1292:        if(chdir(ctrl_dir)!=0) {
        !          1293:                sprintf(str,"!ERROR %d changing directory to: %s", errno, ctrl_dir);
        !          1294:                svc_lputs(NULL,LOG_ERR,str);
        !          1295:        }
        !          1296: 
        !          1297:        for(i=1;i<argc;i++) {
        !          1298:                arg=argv[i];
        !          1299:                while(*arg=='-' || *arg=='/')
        !          1300:                        arg++;
        !          1301:                if(!stricmp(arg,"help") || *arg=='?')
        !          1302:                        start_services=FALSE;
        !          1303: 
        !          1304:                if(!stricmp(arg,"list"))
        !          1305:                        return list(argv[i+1]);
        !          1306: 
        !          1307:                if(!stricmp(arg,"install"))
        !          1308:                        return install(argv[i+1]);
        !          1309: 
        !          1310:                if(!stricmp(arg,"remove"))
        !          1311:                        return uninstall(argv[i+1]);
        !          1312: 
        !          1313:                if(!stricmp(arg,"disable"))
        !          1314:                        return enable(argv[i+1], FALSE);
        !          1315: 
        !          1316:                if(!stricmp(arg,"enable"))
        !          1317:                        return enable(argv[i+1], TRUE);
        !          1318: 
        !          1319:                if(!stricmp(arg,"stop"))
        !          1320:                        return control(argv[i+1],SERVICE_CONTROL_STOP);
        !          1321: 
        !          1322:                if(!stricmp(arg,"start"))
        !          1323:                        return start(argv[i+1],argc,argv);
        !          1324: 
        !          1325:                if(!stricmp(arg,"recycle"))
        !          1326:                        return control(argv[i+1],SERVICE_CONTROL_RECYCLE);
        !          1327: 
        !          1328:                if(!stricmp(arg,"mute"))
        !          1329:                        return control(argv[i+1],SERVICE_CONTROL_MUTE);
        !          1330: 
        !          1331:                if(!stricmp(arg,"unmute"))
        !          1332:                        return control(argv[i+1],SERVICE_CONTROL_UNMUTE);
        !          1333:        }
        !          1334: 
        !          1335:        if(start_services) {
        !          1336:                printf("Starting service control dispatcher.\n" );
        !          1337:                printf("This may take several seconds.  Please wait.\n" );
        !          1338: 
        !          1339:                if(StartServiceCtrlDispatcher(ServiceDispatchTable))
        !          1340:                        return(0);
        !          1341: 
        !          1342:                sprintf(str,"!ERROR %u starting service control dispatcher",GetLastError());
        !          1343:                printf("%s\n\n",str);
        !          1344:                OutputDebugString(str); 
        !          1345:        }
        !          1346: 
        !          1347:        SAFECOPY(str,getfname(argv[0]));
        !          1348:        if((p=getfext(str))!=NULL)
        !          1349:                *p=0;
        !          1350: 
        !          1351:        printf("Usage: %s [command] [service]\n", str);
        !          1352: 
        !          1353:        printf("\nIf service name not specified, default is ALL services.\n");
        !          1354: 
        !          1355:        printf("\nAvailable Commands:\n\n");
        !          1356:        printf("%-20s %s\n","list","to list services");
        !          1357:     printf("%-20s %s\n","install","to install services");
        !          1358:     printf("%-20s %s\n","remove","to remove serivces");
        !          1359:     printf("%-20s %s\n","disable","to disable services");
        !          1360:     printf("%-20s %s\n","enable","to re-enable disabled services");
        !          1361:     printf("%-20s %s\n","start","to start services");
        !          1362:     printf("%-20s %s\n","stop","to stop services");
        !          1363:        printf("%-20s %s\n","recycle","to recycle services");
        !          1364:        printf("%-20s %s\n","mute","to mute (sounds of) services");
        !          1365:        printf("%-20s %s\n","unmute","to unmute (sounds of) services");
        !          1366: 
        !          1367:        printf("\nAvailable Services:\n\n");
        !          1368:        printf("%-20s %s\n","Name","Description");
        !          1369:        printf("%-20s %s\n","----","-----------");
        !          1370:        for(i=0;ntsvc_list[i]!=NULL;i++)
        !          1371:                printf("%-20s %s\n",ntsvc_list[i]->name+STRLEN_SYNCHRONET,ntsvc_list[i]->display_name);
        !          1372: 
        !          1373:        return(0);
        !          1374: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.