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

1.1     ! root        1: /* ntsrvcs.c */
        !             2: 
        !             3: /* Synchronet BBS as a set of Windows NT Services */
        !             4: 
        !             5: /* $Id: ntsvcs.c,v 1.24 2004/12/04 16:45:30 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 2004 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: 
        !            54: static void WINAPI bbs_ctrl_handler(DWORD dwCtrlCode);
        !            55: static void WINAPI ftp_ctrl_handler(DWORD dwCtrlCode);
        !            56: static void WINAPI web_ctrl_handler(DWORD dwCtrlCode);
        !            57: static void WINAPI mail_ctrl_handler(DWORD dwCtrlCode);
        !            58: static void WINAPI services_ctrl_handler(DWORD dwCtrlCode);
        !            59: 
        !            60: /* Global variables */
        !            61: 
        !            62: char                           ini_file[MAX_PATH+1];
        !            63: bbs_startup_t          bbs_startup;
        !            64: ftp_startup_t          ftp_startup;
        !            65: mail_startup_t         mail_startup;
        !            66: services_startup_t     services_startup;
        !            67: web_startup_t          web_startup;
        !            68: 
        !            69: typedef struct {
        !            70:        char*                                   name;
        !            71:        char*                                   display_name;
        !            72:        char*                                   description;
        !            73:        void*                                   startup;
        !            74:        DWORD*                                  options;
        !            75:        BOOL*                                   recycle_now;
        !            76:        DWORD*                                  log_mask;
        !            77:        void                                    (*thread)(void* arg);
        !            78:        void                                    (*terminate)(void);
        !            79:        void                                    (WINAPI *ctrl_handler)(DWORD);
        !            80:        HANDLE                                  log_handle;
        !            81:        HANDLE                                  event_handle;
        !            82:        BOOL                                    autostart;
        !            83:        BOOL                                    debug;
        !            84:        SERVICE_STATUS                  status;
        !            85:        SERVICE_STATUS_HANDLE   status_handle;
        !            86: } sbbs_ntsvc_t;
        !            87: 
        !            88: sbbs_ntsvc_t bbs ={    
        !            89:        NTSVC_NAME_BBS,
        !            90:        "Synchronet Telnet/RLogin Server",
        !            91:        "Provides support for Telnet and RLogin clients and executes timed events. " \
        !            92:                "This service provides the critical functions of your Synchronet BBS.",
        !            93:        &bbs_startup,
        !            94:        &bbs_startup.options,
        !            95:        &bbs_startup.recycle_now,
        !            96:        &bbs_startup.log_mask,
        !            97:        bbs_thread,
        !            98:        bbs_terminate,
        !            99:        bbs_ctrl_handler,
        !           100:        INVALID_HANDLE_VALUE
        !           101: };
        !           102: 
        !           103: /* This is not (currently) a separate service, use this for logging only */
        !           104: sbbs_ntsvc_t event ={  
        !           105:        NTSVC_NAME_EVENT,
        !           106:        NULL,
        !           107:        NULL,
        !           108:        NULL,
        !           109:        NULL,
        !           110:        NULL,
        !           111:        &bbs_startup.log_mask,
        !           112:        NULL,
        !           113:        NULL,
        !           114:        NULL,
        !           115:        INVALID_HANDLE_VALUE
        !           116: };
        !           117: 
        !           118: sbbs_ntsvc_t ftp = {
        !           119:        NTSVC_NAME_FTP,
        !           120:        "Synchronet FTP Server",
        !           121:        "Provides support for FTP clients (including web browsers) for file transfers.",
        !           122:        &ftp_startup,
        !           123:        &ftp_startup.options,
        !           124:        &ftp_startup.recycle_now,
        !           125:        &ftp_startup.log_mask,
        !           126:        ftp_server,
        !           127:        ftp_terminate,
        !           128:        ftp_ctrl_handler,
        !           129:        INVALID_HANDLE_VALUE
        !           130: };
        !           131: 
        !           132: sbbs_ntsvc_t web = {
        !           133:        NTSVC_NAME_WEB,
        !           134:        "Synchronet Web Server",
        !           135:        "Provides support for Web (HTML/HTTP) clients (browsers).",
        !           136:        &web_startup,
        !           137:        &web_startup.options,
        !           138:        &web_startup.recycle_now,
        !           139:        &web_startup.log_mask,
        !           140:        web_server,
        !           141:        web_terminate,
        !           142:        web_ctrl_handler,
        !           143:        INVALID_HANDLE_VALUE
        !           144: };
        !           145: 
        !           146: sbbs_ntsvc_t mail = {
        !           147:        NTSVC_NAME_MAIL,
        !           148:        "Synchronet SMTP/POP3 Mail Server",
        !           149:        "Sends and receives Internet e-mail (using SMTP) and allows users to remotely " \
        !           150:                "access their e-mail using an Internet mail client (using POP3).",
        !           151:        &mail_startup,
        !           152:        &mail_startup.options,
        !           153:        &mail_startup.recycle_now,
        !           154:        &mail_startup.log_mask,
        !           155:        mail_server,
        !           156:        mail_terminate,
        !           157:        mail_ctrl_handler,
        !           158:        INVALID_HANDLE_VALUE
        !           159: };
        !           160: 
        !           161: sbbs_ntsvc_t services = {
        !           162:        NTSVC_NAME_SERVICES,
        !           163:        "Synchronet Services",
        !           164:        "Plugin servers (usually in JavaScript) for any TCP/UDP protocol. " \
        !           165:                "Stock services include Finger, Gopher, NNTP, and IRC. Edit your ctrl/services.ini " \
        !           166:                "file for configuration of individual Synchronet Services.",
        !           167:        &services_startup,
        !           168:        &services_startup.options,
        !           169:        &services_startup.recycle_now,
        !           170:        &services_startup.log_mask,
        !           171:        services_thread,
        !           172:        services_terminate,
        !           173:        services_ctrl_handler,
        !           174:        INVALID_HANDLE_VALUE
        !           175: };
        !           176: 
        !           177: /* This list is used for enumerating all services */
        !           178: sbbs_ntsvc_t* ntsvc_list[] = {
        !           179:        &bbs,
        !           180:        &ftp,
        !           181:        &web,
        !           182:        &mail,
        !           183:        &services,
        !           184:        NULL
        !           185: };
        !           186:                                                        
        !           187: /****************************************/
        !           188: /* Service Control Handlers (Callbacks) */
        !           189: /****************************************/
        !           190: 
        !           191: /* Common control handler for all services */
        !           192: static void svc_ctrl_handler(sbbs_ntsvc_t* svc, DWORD dwCtrlCode)
        !           193: {
        !           194:        switch(dwCtrlCode) {
        !           195:                case SERVICE_CONTROL_RECYCLE:
        !           196:                        *svc->recycle_now=TRUE;
        !           197:                        break;
        !           198:                case SERVICE_CONTROL_MUTE:
        !           199:                        *svc->options|=BBS_OPT_MUTE;
        !           200:                        break;
        !           201:                case SERVICE_CONTROL_UNMUTE:
        !           202:                        *svc->options&=~BBS_OPT_MUTE;
        !           203:                        break;
        !           204:                case SERVICE_CONTROL_STOP:
        !           205:                case SERVICE_CONTROL_SHUTDOWN:
        !           206:                        svc->terminate();
        !           207:                        svc->status.dwWaitHint=NTSVC_TIMEOUT_TERMINATE;
        !           208:                        svc->status.dwCurrentState=SERVICE_STOP_PENDING;
        !           209:                        break;
        !           210:        }
        !           211:        SetServiceStatus(svc->status_handle, &svc->status);
        !           212: }
        !           213: 
        !           214: /* Service-specific control handler stub functions */
        !           215: static void WINAPI bbs_ctrl_handler(DWORD dwCtrlCode)
        !           216: {
        !           217:        switch(dwCtrlCode) {
        !           218:                case SERVICE_CONTROL_SYSOP_AVAILABLE:
        !           219:                        bbs_startup.options|=BBS_OPT_SYSOP_AVAILABLE;
        !           220:                        break;
        !           221:                case SERVICE_CONTROL_SYSOP_UNAVAILABLE:
        !           222:                        bbs_startup.options&=~BBS_OPT_SYSOP_AVAILABLE;
        !           223:                        break;
        !           224:                default:
        !           225:                        svc_ctrl_handler(&bbs, dwCtrlCode);
        !           226:                        break;
        !           227:        }
        !           228: }
        !           229: 
        !           230: static void WINAPI ftp_ctrl_handler(DWORD dwCtrlCode)
        !           231: {
        !           232:        svc_ctrl_handler(&ftp, dwCtrlCode);
        !           233: }
        !           234: 
        !           235: static void WINAPI web_ctrl_handler(DWORD dwCtrlCode)
        !           236: {
        !           237:        svc_ctrl_handler(&web, dwCtrlCode);
        !           238: }
        !           239: 
        !           240: static void WINAPI mail_ctrl_handler(DWORD dwCtrlCode)
        !           241: {
        !           242:        svc_ctrl_handler(&mail, dwCtrlCode);
        !           243: }
        !           244: 
        !           245: static void WINAPI services_ctrl_handler(DWORD dwCtrlCode)
        !           246: {
        !           247:        svc_ctrl_handler(&services, dwCtrlCode);
        !           248: }
        !           249: 
        !           250: static WORD event_type(int level)
        !           251: {
        !           252:        switch(level) {
        !           253:                case LOG_WARNING:
        !           254:                        return(EVENTLOG_WARNING_TYPE);
        !           255:                case LOG_NOTICE:
        !           256:                case LOG_INFO:
        !           257:                case LOG_DEBUG:
        !           258:                        return(EVENTLOG_INFORMATION_TYPE);      /* same as EVENT_LOG_SUCCESS */
        !           259:        }
        !           260: /*
        !           261:        LOG_EMERG
        !           262:        LOG_ALERT
        !           263:        LOG_CRIT
        !           264:        LOG_ERR
        !           265: */
        !           266:        return(EVENTLOG_ERROR_TYPE);
        !           267: }
        !           268: 
        !           269: /**************************************/
        !           270: /* Common Service Log Ouptut Function */
        !           271: /**************************************/
        !           272: static int svc_lputs(void* p, int level, char* str)
        !           273: {
        !           274:        char    debug[1024];
        !           275:        char    fname[256];
        !           276:        DWORD   len;
        !           277:        DWORD   wr;
        !           278:        sbbs_ntsvc_t* svc = (sbbs_ntsvc_t*)p;
        !           279: 
        !           280:        /* Debug Logging */
        !           281:        if(svc==NULL || svc->debug) {
        !           282:                snprintf(debug,sizeof(debug),"%s: %s",svc==NULL ? "Synchronet" : svc->name, str);
        !           283:                OutputDebugString(debug);
        !           284:        }
        !           285:        if(svc==NULL)
        !           286:                return(0);
        !           287: 
        !           288:        len = strlen(str);
        !           289: 
        !           290:        /* Mailslot Logging (for sbbsctrl) */
        !           291:        if(svc->log_handle != INVALID_HANDLE_VALUE /* Invalid log handle? */
        !           292:                && !GetMailslotInfo(svc->log_handle, NULL, NULL, NULL, NULL)) {
        !           293:                /* Close and try to re-open */
        !           294:                CloseHandle(svc->log_handle);
        !           295:                svc->log_handle=INVALID_HANDLE_VALUE;
        !           296:        }
        !           297: 
        !           298:        if(svc->log_handle == INVALID_HANDLE_VALUE) {
        !           299:                sprintf(fname,"\\\\.\\mailslot\\%s.log",svc->name);
        !           300:                svc->log_handle = CreateFile(
        !           301:                        fname,                                  // pointer to name of the file
        !           302:                        GENERIC_WRITE,                  // access (read-write) mode
        !           303:                        FILE_SHARE_READ,                // share mode
        !           304:                        NULL,                                   // pointer to security attributes
        !           305:                        OPEN_EXISTING,                  // how to create
        !           306:                        FILE_ATTRIBUTE_NORMAL,  // file attributes
        !           307:                        NULL                                    // handle to file with attributes to copy
        !           308:                        );
        !           309:        }
        !           310:        if(svc->log_handle != INVALID_HANDLE_VALUE) {
        !           311:                if(!WriteFile(svc->log_handle,str,len,&wr,NULL) || wr!=len) {
        !           312:                        /* This most likely indicates the server closed the mailslot */
        !           313:                        sprintf(debug,"!ERROR %d writing %u bytes to %s pipe (wr=%d)"
        !           314:                                ,GetLastError(),len,svc->name,wr);
        !           315:                        OutputDebugString(debug);
        !           316:                        /* So close the handle and attempt re-open next time */
        !           317:                        CloseHandle(svc->log_handle);
        !           318:                        svc->log_handle=INVALID_HANDLE_VALUE;
        !           319:                }
        !           320:        }
        !           321:        
        !           322:        /* Event Logging */
        !           323:        if((*svc->log_mask)&(1<<level)) {
        !           324:                if(svc->event_handle == NULL)
        !           325:                        svc->event_handle = RegisterEventSource(
        !           326:                                NULL,           // server name for source (NULL = local computer)
        !           327:                                svc->name   // source name for registered handle
        !           328:                                );
        !           329:                if(svc->event_handle != NULL)
        !           330:                        ReportEvent(svc->event_handle,  // event log handle
        !           331:                                event_type(level),              // event type
        !           332:                                0,                                              // category zero
        !           333:                                0,                                              // event identifier
        !           334:                                NULL,                                   // no user security identifier
        !           335:                                1,                                              // one string
        !           336:                                0,                                              // no data
        !           337:                                &str,                                   // pointer to string array
        !           338:                                NULL);                                  // pointer to data
        !           339:        }
        !           340: 
        !           341:     return(0);
        !           342: }
        !           343: 
        !           344: /****************************************************************************/
        !           345: /* Event thread local/log print routine                                                                                */
        !           346: /****************************************************************************/
        !           347: static int event_lputs(int level, char *str)
        !           348: {
        !           349:        svc_lputs(&event,level,str);
        !           350:     return(0);
        !           351: }
        !           352: 
        !           353: /************************************/
        !           354: /* Shared Service Callback Routines */
        !           355: /************************************/
        !           356: 
        !           357: static void svc_started(void* p)
        !           358: {
        !           359:        sbbs_ntsvc_t* svc = (sbbs_ntsvc_t*)p;
        !           360: 
        !           361:        svc->status.dwCurrentState=SERVICE_RUNNING;
        !           362:        svc->status.dwControlsAccepted|=SERVICE_ACCEPT_STOP;
        !           363:        SetServiceStatus(svc->status_handle, &svc->status);
        !           364: }
        !           365: 
        !           366: static void svc_recycle(void *p)
        !           367: {
        !           368:        char    str[MAX_PATH*2];
        !           369:        FILE*   fp;
        !           370:        sbbs_ntsvc_t* svc = (sbbs_ntsvc_t*)p;
        !           371:        bbs_startup_t*          bbs_startup=NULL;
        !           372:        ftp_startup_t*          ftp_startup=NULL;
        !           373:        mail_startup_t*         mail_startup=NULL;
        !           374:        services_startup_t*     services_startup=NULL;
        !           375:        web_startup_t*          web_startup=NULL;
        !           376: 
        !           377:        if(svc==&bbs)
        !           378:                bbs_startup=svc->startup;
        !           379:        else if(svc==&ftp)
        !           380:                ftp_startup=svc->startup;
        !           381:        else if(svc==&web)
        !           382:                web_startup=svc->startup;
        !           383:        else if(svc==&mail)
        !           384:                mail_startup=svc->startup;
        !           385:        else if(svc==&services)
        !           386:                services_startup=svc->startup;
        !           387: 
        !           388:        SAFEPRINTF(str,"Reading %s",ini_file);
        !           389:        svc_lputs(svc,LOG_INFO,str);
        !           390: 
        !           391:        /* Read .ini file here */
        !           392:        fp=fopen(ini_file,"r");
        !           393: 
        !           394:        /* We call this function to set defaults, even if there's no .ini file */
        !           395:        sbbs_read_ini(fp 
        !           396:                ,NULL   /* global_startup */
        !           397:                ,NULL   ,bbs_startup
        !           398:                ,NULL   ,ftp_startup 
        !           399:                ,NULL   ,web_startup
        !           400:                ,NULL   ,mail_startup 
        !           401:                ,NULL   ,services_startup
        !           402:                );
        !           403: 
        !           404:        /* close .ini file here */
        !           405:        if(fp!=NULL)
        !           406:                fclose(fp);
        !           407: }
        !           408: 
        !           409: static void svc_terminated(void* p, int code)
        !           410: {
        !           411:        sbbs_ntsvc_t* svc = (sbbs_ntsvc_t*)p;
        !           412: 
        !           413:        if(code) {
        !           414:                svc->status.dwWin32ExitCode=ERROR_SERVICE_SPECIFIC_ERROR;
        !           415:                svc->status.dwServiceSpecificExitCode=code;
        !           416:                SetServiceStatus(svc->status_handle, &svc->status);
        !           417:        }
        !           418: }
        !           419: 
        !           420: static void svc_clients(void* p, int active)
        !           421: {
        !           422:        sbbs_ntsvc_t* svc = (sbbs_ntsvc_t*)p;
        !           423: }
        !           424: 
        !           425: /***************/
        !           426: /* ServiceMain */
        !           427: /***************/
        !           428: 
        !           429: /* Common ServiceMain for all services */
        !           430: static void WINAPI svc_main(sbbs_ntsvc_t* svc, DWORD argc, LPTSTR *argv)
        !           431: {
        !           432:        char    str[256];
        !           433:        DWORD   i;
        !           434:        char*   arg;
        !           435: 
        !           436:        for(i=0;i<argc;i++) {
        !           437:                arg=argv[i];
        !           438:                if(*arg=='-' || *arg=='/')
        !           439:                        arg++;
        !           440:                if(!stricmp(arg,"debug"))
        !           441:                        svc->debug=TRUE;
        !           442:                if(!stricmp(arg,"logmask") && i+1<argc)
        !           443:                        (*svc->log_mask)=strtol(argv[++i],NULL,0);
        !           444:        }
        !           445: 
        !           446:        sprintf(str,"Starting NT Service: %s",svc->display_name);
        !           447:        svc_lputs(svc,LOG_INFO,str);
        !           448: 
        !           449:     if((svc->status_handle = RegisterServiceCtrlHandler(svc->name, svc->ctrl_handler))==0) {
        !           450:                sprintf(str,"!ERROR %d registering service control handler",GetLastError());
        !           451:                svc_lputs(NULL,LOG_ERR,str);
        !           452:                return;
        !           453:        }
        !           454: 
        !           455:        memset(&svc->status,0,sizeof(SERVICE_STATUS));
        !           456:        svc->status.dwServiceType=SERVICE_WIN32_SHARE_PROCESS;
        !           457:        svc->status.dwControlsAccepted=SERVICE_ACCEPT_SHUTDOWN;
        !           458:        svc->status.dwWaitHint=NTSVC_TIMEOUT_STARTUP;
        !           459: 
        !           460:        svc->status.dwCurrentState=SERVICE_START_PENDING;
        !           461:        SetServiceStatus(svc->status_handle, &svc->status);
        !           462: 
        !           463:        svc->thread(svc->startup);
        !           464: 
        !           465:        svc->status.dwCurrentState=SERVICE_STOPPED;
        !           466:        SetServiceStatus(svc->status_handle, &svc->status);
        !           467: 
        !           468:        if(svc->log_handle!=INVALID_HANDLE_VALUE) {
        !           469:                CloseHandle(svc->log_handle);
        !           470:                svc->log_handle=INVALID_HANDLE_VALUE;
        !           471:        }
        !           472: 
        !           473:        if(svc->event_handle!=NULL) {
        !           474:                DeregisterEventSource(svc->event_handle);
        !           475:                svc->event_handle=NULL;
        !           476:        }
        !           477: }
        !           478: 
        !           479: /* Service-specific ServiceMain stub functions */
        !           480: 
        !           481: static void WINAPI bbs_start(DWORD dwArgc, LPTSTR *lpszArgv)
        !           482: {
        !           483:        svc_main(&bbs, dwArgc, lpszArgv);
        !           484: 
        !           485:        /* Events are (currently) part of the BBS service */
        !           486:        if(event.log_handle!=INVALID_HANDLE_VALUE) {
        !           487:                CloseHandle(event.log_handle);
        !           488:                event.log_handle=INVALID_HANDLE_VALUE;
        !           489:        }
        !           490: }
        !           491: 
        !           492: static void WINAPI ftp_start(DWORD dwArgc, LPTSTR *lpszArgv)
        !           493: {
        !           494:        svc_main(&ftp, dwArgc, lpszArgv);
        !           495: }
        !           496: 
        !           497: static void WINAPI web_start(DWORD dwArgc, LPTSTR *lpszArgv)
        !           498: {
        !           499:        svc_main(&web, dwArgc, lpszArgv);
        !           500: }
        !           501: 
        !           502: static void WINAPI mail_start(DWORD dwArgc, LPTSTR *lpszArgv)
        !           503: {
        !           504:        svc_main(&mail, dwArgc, lpszArgv);
        !           505: }
        !           506: 
        !           507: static void WINAPI services_start(DWORD dwArgc, LPTSTR *lpszArgv)
        !           508: {
        !           509:        svc_main(&services, dwArgc, lpszArgv);
        !           510: }
        !           511: 
        !           512: /******************************************/
        !           513: /* NT Serivce Install/Uninstall Functions */
        !           514: /******************************************/
        !           515: 
        !           516: /* ChangeServiceConfig2 is a Win2K+ API function, must call dynamically */
        !           517: typedef WINADVAPI BOOL (WINAPI *ChangeServiceConfig2_t)(SC_HANDLE, DWORD, LPCVOID);
        !           518: 
        !           519: static void describe_service(HANDLE hSCMlib, SC_HANDLE hService, char* description)
        !           520: {
        !           521:        ChangeServiceConfig2_t changeServiceConfig2;
        !           522:        static SERVICE_DESCRIPTION service_desc;
        !           523:   
        !           524:        if(hSCMlib==NULL)
        !           525:                return;
        !           526: 
        !           527:        service_desc.lpDescription=description;
        !           528: 
        !           529:        if((changeServiceConfig2 = (ChangeServiceConfig2_t)GetProcAddress(hSCMlib, "ChangeServiceConfig2A"))!=NULL)
        !           530:                changeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &service_desc);
        !           531: }
        !           532: 
        !           533: static BOOL register_event_source(char* name, char* path)
        !           534: {
        !           535:        char    keyname[256];
        !           536:        HKEY    hKey;
        !           537:        DWORD   type;
        !           538:        DWORD   disp;
        !           539:        LONG    retval;
        !           540:        char*   value;
        !           541: 
        !           542:        sprintf(keyname,"system\\CurrentControlSet\\services\\eventlog\\application\\%s",name);
        !           543: 
        !           544:        retval=RegCreateKeyEx(
        !           545:                HKEY_LOCAL_MACHINE,                     // handle to an open key
        !           546:                keyname,                        // address of subkey name
        !           547:                0,                              // reserved
        !           548:                "",                             // address of class string
        !           549:                0,                              // special options flag
        !           550:                KEY_ALL_ACCESS, // desired security access
        !           551:                NULL,           // address of key security structure
        !           552:                &hKey,                  // address of buffer for opened handle
        !           553:                &disp                   // address of disposition value buffer
        !           554:                );
        !           555: 
        !           556:        if(retval!=ERROR_SUCCESS) {
        !           557:                fprintf(stderr,"!Error %d creating/opening registry key (HKLM\\%s)\n"
        !           558:                        ,retval,keyname);
        !           559:                return(FALSE);
        !           560:        }
        !           561: 
        !           562:        value="EventMessageFile";
        !           563:        retval=RegSetValueEx(
        !           564:                hKey,                   // handle to key to set value for
        !           565:                value,                  // name of the value to set
        !           566:                0,                              // reserved
        !           567:                REG_SZ,                 // flag for value type
        !           568:                path,                   // address of value data
        !           569:                strlen(path)    // size of value data
        !           570:                );
        !           571: 
        !           572:        if(retval!=ERROR_SUCCESS) {
        !           573:                RegCloseKey(hKey);
        !           574:                fprintf(stderr,"!Error %d setting registry key value (%s)\n"
        !           575:                        ,retval,value);
        !           576:                return(FALSE);
        !           577:        }
        !           578: 
        !           579:        value="TypesSupported";
        !           580:        type=EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
        !           581:        retval=RegSetValueEx(
        !           582:                hKey,                   // handle to key to set value for
        !           583:                value,                  // name of the value to set
        !           584:                0,                              // reserved
        !           585:                REG_DWORD,              // flag for value type
        !           586:                (BYTE*)&type,   // address of value data
        !           587:                sizeof(type)    // size of value data
        !           588:                );
        !           589: 
        !           590:        RegCloseKey(hKey);
        !           591: 
        !           592:        if(retval!=ERROR_SUCCESS) {
        !           593:                fprintf(stderr,"!Error %d setting registry key value (%s)\n"
        !           594:                        ,retval,value);
        !           595:                return(FALSE);
        !           596:        }
        !           597: 
        !           598:        return(TRUE);
        !           599: }
        !           600: 
        !           601: /****************************************************************************/
        !           602: /* Utility function to create a service with description (on Win2K+)           */
        !           603: /****************************************************************************/
        !           604: static SC_HANDLE create_service(HANDLE hSCMlib, SC_HANDLE hSCManager
        !           605:                                                                ,char* name, char* display_name, char* description, char* path
        !           606:                                                                ,BOOL autostart)
        !           607: {
        !           608:     SC_HANDLE   hService;
        !           609: 
        !           610:        printf("Installing service: %-40s ... ", display_name);
        !           611: 
        !           612:     hService = CreateService(
        !           613:         hSCManager,                                            // SCManager database
        !           614:         name,                                                  // name of service
        !           615:         display_name,                                  // name to display
        !           616:         SERVICE_ALL_ACCESS,                            // desired access
        !           617:         SERVICE_WIN32_SHARE_PROCESS,   // service type
        !           618:                autostart                                               // start type (auto or manual)
        !           619:                        ? SERVICE_AUTO_START : SERVICE_DEMAND_START,                            
        !           620:         SERVICE_ERROR_NORMAL,                  // error control type
        !           621:         path,                                                  // service's binary
        !           622:         NULL,                                                  // no load ordering group
        !           623:         NULL,                                                  // no tag identifier
        !           624:         "",                                                            // dependencies
        !           625:         NULL,                                                  // LocalSystem account
        !           626:         NULL);                                                 // no password
        !           627: 
        !           628:        if(hService==NULL)
        !           629:                printf("!ERROR %d\n",GetLastError());
        !           630:        else {
        !           631:                describe_service(hSCMlib, hService,description);
        !           632:                CloseServiceHandle(hService);
        !           633:                printf("Successful\n");
        !           634: 
        !           635:                register_event_source(name,path);
        !           636:        }
        !           637: 
        !           638:        return(hService);
        !           639: }
        !           640: 
        !           641: /****************************************************************************/
        !           642: /* Install one or all services                                                                                         */
        !           643: /****************************************************************************/
        !           644: static int install(const char* svc_name)
        !           645: {
        !           646:        int                     i;
        !           647:        HANDLE          hSCMlib;
        !           648:     SC_HANDLE   hSCManager;
        !           649:     char               path[MAX_PATH+1];
        !           650: 
        !           651:        printf("Installing Synchronet NT Services...\n");
        !           652: 
        !           653:        hSCMlib = LoadLibrary("ADVAPI32.DLL");
        !           654: 
        !           655:     if(GetModuleFileName(NULL,path,sizeof(path))==0)
        !           656:     {
        !           657:         fprintf(stderr,"!ERROR %d getting module file name\n",GetLastError());
        !           658:         return(-1);
        !           659:     }
        !           660: 
        !           661:     hSCManager = OpenSCManager(
        !           662:                         NULL,                   // machine (NULL == local)
        !           663:                         NULL,                   // database (NULL == default)
        !           664:                         SC_MANAGER_ALL_ACCESS   // access required
        !           665:                         );
        !           666:     if(hSCManager==NULL) {
        !           667:                fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError());
        !           668:                return(-1);
        !           669:        }
        !           670: 
        !           671:        for(i=0;ntsvc_list[i]!=NULL;i++)
        !           672:                if(svc_name==NULL       /* All? */
        !           673:                        || !stricmp(ntsvc_list[i]->name, svc_name))
        !           674:                        create_service(hSCMlib
        !           675:                                ,hSCManager
        !           676:                                ,ntsvc_list[i]->name
        !           677:                                ,ntsvc_list[i]->display_name
        !           678:                                ,ntsvc_list[i]->description
        !           679:                                ,path
        !           680:                                ,ntsvc_list[i]->autostart);
        !           681: 
        !           682:        if(hSCMlib!=NULL)
        !           683:                FreeLibrary(hSCMlib);
        !           684: 
        !           685:        CloseServiceHandle(hSCManager);
        !           686: 
        !           687:        return(0);
        !           688: }
        !           689: 
        !           690: /****************************************************************************/
        !           691: /* Utility function to remove a service cleanly (stopping if necessary)                */
        !           692: /****************************************************************************/
        !           693: static void remove_service(SC_HANDLE hSCManager, char* name, char* disp_name)
        !           694: {
        !           695:     SC_HANDLE          hService;
        !           696:        SERVICE_STATUS  status;
        !           697: 
        !           698:        printf("Removing service: %-40s ... ", disp_name);
        !           699: 
        !           700:     hService = OpenService(hSCManager, name, SERVICE_ALL_ACCESS);
        !           701: 
        !           702:        if(hService==NULL) {
        !           703:                printf("\n!ERROR %d opening service: %s\n",GetLastError(),name);
        !           704:                return;
        !           705:        }
        !           706: 
        !           707:     // try to stop the service
        !           708:     if(ControlService( hService, SERVICE_CONTROL_STOP, &status))
        !           709:     {
        !           710:         printf("\nStopping: %s ... ",name);
        !           711: 
        !           712:         while(QueryServiceStatus(hService, &status) && status.dwCurrentState == SERVICE_STOP_PENDING)
        !           713:                        Sleep(1000);
        !           714: 
        !           715:         if(status.dwCurrentState == SERVICE_STOPPED)
        !           716:             printf("Stopped.\n");
        !           717:         else
        !           718:             printf("FAILED!\n");
        !           719:     }
        !           720: 
        !           721:     // now remove the service
        !           722:     if(DeleteService(hService))
        !           723:                printf("Successful\n");
        !           724:        else
        !           725:                printf("!ERROR %d\n",GetLastError());
        !           726:     CloseServiceHandle(hService);
        !           727: }
        !           728: 
        !           729: /****************************************************************************/
        !           730: /* Uninstall one or all services                                                                                       */
        !           731: /****************************************************************************/
        !           732: static int uninstall(const char* svc_name)
        !           733: {
        !           734:        int                     i;
        !           735:     SC_HANDLE   hSCManager;
        !           736: 
        !           737:     hSCManager = OpenSCManager(
        !           738:                         NULL,                   // machine (NULL == local)
        !           739:                         NULL,                   // database (NULL == default)
        !           740:                         SC_MANAGER_ALL_ACCESS   // access required
        !           741:                         );
        !           742:     if(hSCManager==NULL) {
        !           743:                fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError());
        !           744:                return(-1);
        !           745:        }
        !           746: 
        !           747:        for(i=0;ntsvc_list[i]!=NULL;i++)
        !           748:                if(svc_name==NULL       /* All? */
        !           749:                        || !stricmp(ntsvc_list[i]->name, svc_name))
        !           750:                        remove_service(hSCManager
        !           751:                                ,ntsvc_list[i]->name
        !           752:                                ,ntsvc_list[i]->display_name);
        !           753: 
        !           754:        CloseServiceHandle(hSCManager);
        !           755: 
        !           756:        return(0);
        !           757: }
        !           758: 
        !           759: /****************************************************************************/
        !           760: /* Utility function to disable a service                                                                       */
        !           761: /****************************************************************************/
        !           762: static void set_service_start_type(SC_HANDLE hSCManager, char* name
        !           763:                                                                   ,char* disp_name, DWORD start_type)
        !           764: {
        !           765:     SC_HANDLE          hService;
        !           766: 
        !           767:        printf("%s service: %-40s ... "
        !           768:                ,start_type==SERVICE_DISABLED ? "Disabling" : "Enabling", disp_name);
        !           769: 
        !           770:     hService = OpenService(hSCManager, name, SERVICE_ALL_ACCESS);
        !           771: 
        !           772:        if(hService==NULL) {
        !           773:                printf("\n!ERROR %d opening service: %s\n",GetLastError(),name);
        !           774:                return;
        !           775:        }
        !           776: 
        !           777:        if(!ChangeServiceConfig(
        !           778:                hService,                               // handle to service
        !           779:                SERVICE_NO_CHANGE,              // type of service
        !           780:                start_type,                             // when to start service
        !           781:                SERVICE_NO_CHANGE,              // severity if service fails to start
        !           782:                NULL,                                   // pointer to service binary file name
        !           783:                NULL,                                   // pointer to load ordering group name
        !           784:                NULL,                                   // pointer to variable to get tag identifier
        !           785:                NULL,                                   // pointer to array of dependency names
        !           786:                NULL,                                   // pointer to account name of service
        !           787:                NULL,                                   // pointer to password for service account
        !           788:                NULL                                    // pointer to display name
        !           789:                ))
        !           790:                printf("\n!ERROR %d changing service config for: %s\n",GetLastError(),name);
        !           791:        else
        !           792:                printf("Successful\n");
        !           793: 
        !           794:     CloseServiceHandle(hService);
        !           795: }
        !           796: 
        !           797: /****************************************************************************/
        !           798: /* Enable (set to auto-start) or disable one or all services                           */
        !           799: /****************************************************************************/
        !           800: static int enable(const char* svc_name, BOOL enabled)
        !           801: {
        !           802:        int                     i;
        !           803:     SC_HANDLE   hSCManager;
        !           804: 
        !           805:     hSCManager = OpenSCManager(
        !           806:                         NULL,                   // machine (NULL == local)
        !           807:                         NULL,                   // database (NULL == default)
        !           808:                         SC_MANAGER_ALL_ACCESS   // access required
        !           809:                         );
        !           810:     if(hSCManager==NULL) {
        !           811:                fprintf(stderr,"!ERROR %d opening SC manager\n",GetLastError());
        !           812:                return(-1);
        !           813:        }
        !           814: 
        !           815:        for(i=0;ntsvc_list[i]!=NULL;i++)
        !           816:                if(svc_name==NULL       /* All? */
        !           817:                        || !stricmp(ntsvc_list[i]->name, svc_name))
        !           818:                        set_service_start_type(hSCManager
        !           819:                                ,ntsvc_list[i]->name
        !           820:                                ,ntsvc_list[i]->display_name
        !           821:                                ,enabled ? SERVICE_AUTO_START : SERVICE_DISABLED);
        !           822: 
        !           823:        CloseServiceHandle(hSCManager);
        !           824: 
        !           825:        return(0);
        !           826: }
        !           827: 
        !           828: 
        !           829: /****************************************************************************/
        !           830: /* Main Entry Point                                                                                                                    */
        !           831: /****************************************************************************/
        !           832: int main(int argc, char** argv)
        !           833: {
        !           834:        char*   ctrl_dir;
        !           835:        char*   arg;
        !           836:        char*   p;
        !           837:        char    str[MAX_PATH+1];
        !           838:        int             i;
        !           839:        FILE*   fp=NULL;
        !           840: 
        !           841:        SERVICE_TABLE_ENTRY  ServiceDispatchTable[] = 
        !           842:     { 
        !           843:         { bbs.name,                    bbs_start               }, 
        !           844:                { ftp.name,                     ftp_start               },
        !           845:                { web.name,                     web_start               },
        !           846:                { mail.name,            mail_start              },
        !           847:                { services.name,        services_start  },
        !           848:         { NULL,                                NULL                    }       /* Terminator */
        !           849:     }; 
        !           850: 
        !           851:        printf("\nSynchronet NT Services  Version %s%c  %s\n\n"
        !           852:                ,VERSION,REVISION,COPYRIGHT_NOTICE);
        !           853: 
        !           854:        ctrl_dir=getenv("SBBSCTRL");    /* read from environment variable */
        !           855:        if(ctrl_dir==NULL || ctrl_dir[0]==0) {
        !           856:                ctrl_dir="\\sbbs\\ctrl";                /* Not set? Use default */
        !           857:                printf("!SBBSCTRL environment variable not set, using default value: %s\n\n"
        !           858:                        ,ctrl_dir);
        !           859:        }
        !           860: 
        !           861:        sbbs_get_ini_fname(ini_file, ctrl_dir, NULL /* auto-host_name */);
        !           862: 
        !           863:        /* Initialize BBS startup structure */
        !           864:     memset(&bbs_startup,0,sizeof(bbs_startup));
        !           865:     bbs_startup.size=sizeof(bbs_startup);
        !           866:        bbs_startup.cbdata=&bbs;
        !           867:        bbs_startup.lputs=svc_lputs;
        !           868:        bbs_startup.event_lputs=event_lputs;
        !           869:     bbs_startup.started=svc_started;
        !           870:        bbs_startup.recycle=svc_recycle;
        !           871:     bbs_startup.terminated=svc_terminated;
        !           872:        bbs_startup.clients=svc_clients;
        !           873:     strcpy(bbs_startup.ctrl_dir,ctrl_dir);
        !           874: 
        !           875:        /* Initialize FTP startup structure */
        !           876:     memset(&ftp_startup,0,sizeof(ftp_startup));
        !           877:        ftp_startup.cbdata=&ftp;
        !           878:     ftp_startup.size=sizeof(ftp_startup);
        !           879:        ftp_startup.lputs=svc_lputs;
        !           880:     ftp_startup.started=svc_started;
        !           881:        ftp_startup.recycle=svc_recycle;
        !           882:     ftp_startup.terminated=svc_terminated;
        !           883:        ftp_startup.clients=svc_clients;
        !           884:     strcpy(ftp_startup.ctrl_dir,ctrl_dir);
        !           885: 
        !           886:        /* Initialize Web Server startup structure */
        !           887:     memset(&web_startup,0,sizeof(web_startup));
        !           888:        web_startup.cbdata=&web;
        !           889:     web_startup.size=sizeof(web_startup);
        !           890:        web_startup.lputs=svc_lputs;
        !           891:     web_startup.started=svc_started;
        !           892:        web_startup.recycle=svc_recycle;
        !           893:     web_startup.terminated=svc_terminated;
        !           894:        web_startup.clients=svc_clients;
        !           895:     strcpy(web_startup.ctrl_dir,ctrl_dir);
        !           896: 
        !           897:        /* Initialize Mail Server startup structure */
        !           898:     memset(&mail_startup,0,sizeof(mail_startup));
        !           899:        mail_startup.cbdata=&mail;
        !           900:     mail_startup.size=sizeof(mail_startup);
        !           901:        mail_startup.lputs=svc_lputs;
        !           902:     mail_startup.started=svc_started;
        !           903:        mail_startup.recycle=svc_recycle;
        !           904:     mail_startup.terminated=svc_terminated;
        !           905:        mail_startup.clients=svc_clients;
        !           906:     strcpy(mail_startup.ctrl_dir,ctrl_dir);
        !           907: 
        !           908:        /* Initialize Services startup structure */
        !           909:     memset(&services_startup,0,sizeof(services_startup));
        !           910:        services_startup.cbdata=&services;
        !           911:     services_startup.size=sizeof(services_startup);
        !           912:        services_startup.lputs=svc_lputs;
        !           913:     services_startup.started=svc_started;
        !           914:        services_startup.recycle=svc_recycle;
        !           915:     services_startup.terminated=svc_terminated;
        !           916:        services_startup.clients=svc_clients;
        !           917:     strcpy(services_startup.ctrl_dir,ctrl_dir);
        !           918: 
        !           919:        /* Read .ini file here */
        !           920:        if((fp=fopen(ini_file,"r"))!=NULL) {
        !           921:                sprintf(str,"Reading %s",ini_file);
        !           922:                svc_lputs(NULL,LOG_INFO,str);
        !           923:        }
        !           924: 
        !           925:        /* We call this function to set defaults, even if there's no .ini file */
        !           926:        sbbs_read_ini(fp 
        !           927:                ,NULL   /* global_startup */
        !           928:                ,&bbs.autostart                 ,&bbs_startup
        !           929:                ,&ftp.autostart                 ,&ftp_startup 
        !           930:                ,&web.autostart                 ,&web_startup
        !           931:                ,&mail.autostart                ,&mail_startup 
        !           932:                ,&services.autostart    ,&services_startup
        !           933:                );
        !           934: 
        !           935:        /* close .ini file here */
        !           936:        if(fp!=NULL)
        !           937:                fclose(fp);
        !           938: 
        !           939:        ctrl_dir = bbs_startup.ctrl_dir;
        !           940:        if(chdir(ctrl_dir)!=0) {
        !           941:                sprintf(str,"!ERROR %d changing directory to: %s", errno, ctrl_dir);
        !           942:                svc_lputs(NULL,LOG_ERR,str);
        !           943:        }
        !           944: 
        !           945:        for(i=1;i<argc;i++) {
        !           946:                arg=argv[i];
        !           947:                while(*arg=='-')
        !           948:                        arg++;
        !           949:                if(!stricmp(arg,"install"))
        !           950:                        return install(argv[i+1]);
        !           951: 
        !           952:                if(!stricmp(arg,"remove"))
        !           953:                        return uninstall(argv[i+1]);
        !           954: 
        !           955:                if(!stricmp(arg,"disable"))
        !           956:                        return enable(argv[i+1], FALSE);
        !           957: 
        !           958:                if(!stricmp(arg,"enable"))
        !           959:                        return enable(argv[i+1], TRUE);
        !           960:        }
        !           961: 
        !           962:        printf("Available Services:\n\n");
        !           963:        printf("%-20s %s\n","Name","Description");
        !           964:        printf("%-20s %s\n","----","-----------");
        !           965:        for(i=0;ntsvc_list[i]!=NULL;i++)
        !           966:                printf("%-20s %s\n",ntsvc_list[i]->name,ntsvc_list[i]->display_name);
        !           967: 
        !           968:        SAFECOPY(str,getfname(argv[0]));
        !           969:        if((p=getfext(str))!=NULL)
        !           970:                *p=0;
        !           971: 
        !           972:        printf("\nUsage: %s [command] [service]\n", str);
        !           973: 
        !           974:        printf("\nCommands:\n");
        !           975:     printf("\tinstall\t to install a service by name (default: ALL services)\n");
        !           976:     printf("\tremove\t to remove a service by name (default: ALL services)\n");
        !           977:     printf("\tdisable\t to disable a service by name (default: ALL services)\n");
        !           978:     printf("\tenable\t to re-enable a disabled service (default: ALL services)\n");
        !           979: 
        !           980:     printf("\nStartServiceCtrlDispatcher being called.\n" );
        !           981:     printf("This may take several seconds.  Please wait.\n" );
        !           982: 
        !           983:        if(!StartServiceCtrlDispatcher(ServiceDispatchTable)) 
        !           984:     { 
        !           985:                sprintf(str,"!StartServiceCtrlDispatcher ERROR %d",GetLastError());
        !           986:                printf("%s\n",str);
        !           987:         OutputDebugString(str); 
        !           988:     } 
        !           989: 
        !           990:        return(0);
        !           991: }

unix.superglobalmegacorp.com

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