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

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

unix.superglobalmegacorp.com

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