|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.