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

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

unix.superglobalmegacorp.com

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