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

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

unix.superglobalmegacorp.com

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