--- sbbs/sbbs3/ctrl/mainformunit.cpp 2018/04/24 16:39:34 1.1.1.1 +++ sbbs/sbbs3/ctrl/mainformunit.cpp 2018/04/24 16:40:58 1.1.1.2 @@ -1,12 +1,12 @@ /* Synchronet Control Panel (GUI Borland C++ Builder Project for Win32) */ -/* $Id: mainformunit.cpp,v 1.1.1.1 2018/04/24 16:39:34 root Exp $ */ +/* $Id: mainformunit.cpp,v 1.1.1.2 2018/04/24 16:40:58 root Exp $ */ /**************************************************************************** * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * @@ -35,51 +35,99 @@ //--------------------------------------------------------------------------- #include -#include /* TRegistry */ +#include /* TRegistry */ #pragma hdrstop #include // IPPORT_TELNET, INADDR_ANY #include // _beginthread() #include #include -#include -#include +#include +#include #include #include #include "MainFormUnit.h" #include "TelnetFormUnit.h" +#include "EventsFormUnit.h" +#include "ServicesFormUnit.h" #include "FtpFormUnit.h" +#include "WebFormUnit.h" #include "MailFormUnit.h" #include "NodeFormUnit.h" + #include "StatsFormUnit.h" #include "ClientFormUnit.h" #include "CtrlPathDialogUnit.h" #include "TelnetCfgDlgUnit.h" #include "MailCfgDlgUnit.h" #include "FtpCfgDlgUnit.h" +#include "WebCfgDlgUnit.h" +#include "ServicesCfgDlgUnit.h" #include "AboutBoxFormUnit.h" #include "CodeInputFormUnit.h" #include "TextFileEditUnit.h" #include "UserListFormUnit.h" +#include "PropertiesDlgUnit.h" +#include "ConfigWizardUnit.h" +#include "PreviewFormUnit.h" #include "sbbs.h" // unixtodstr() +#include "sbbs_ini.h" // sbbs_read_ini() #include "userdat.h" // lastuser() +#include "ntsvcs.h" // NTSVC_NAME_* //--------------------------------------------------------------------------- #pragma package(smart_init) +#pragma link "trayicon" +#pragma link "Trayicon" #pragma resource "*.dfm" TMainForm *MainForm; -extern "C" __declspec(dllimport) BOOL __stdcall load_cfg(scfg_t* cfg, char* text[]); -extern "C" __declspec(dllimport) BOOL __stdcall getstats(scfg_t* cfg, char node, stats_t* stats); -extern "C" __declspec(dllimport) int __stdcall getmail(scfg_t* cfg, int usernumber, BOOL sent); -#define MAX_LOGLEN 20000 - #define LOG_TIME_FMT " m/d hh:mm:ssa/p" -int threads=1; +/* Service functions are NT-only, must call dynamically :-( */ +typedef WINADVAPI SC_HANDLE (WINAPI *OpenSCManager_t)(LPCTSTR,LPCTSTR,DWORD); +typedef WINADVAPI SC_HANDLE (WINAPI *OpenService_t)(SC_HANDLE,LPCTSTR,DWORD); +typedef WINADVAPI BOOL (WINAPI *StartService_t)(SC_HANDLE,DWORD,LPCTSTR*); +typedef WINADVAPI BOOL (WINAPI *ControlService_t)(SC_HANDLE,DWORD,LPSERVICE_STATUS); +typedef WINADVAPI BOOL (WINAPI *QueryServiceStatus_t)(SC_HANDLE,LPSERVICE_STATUS); +typedef WINADVAPI BOOL (WINAPI *QueryServiceConfig_t)(SC_HANDLE,LPQUERY_SERVICE_CONFIG,DWORD,LPDWORD); +typedef WINADVAPI BOOL (WINAPI *CloseServiceHandle_t)(SC_HANDLE); + +OpenSCManager_t openSCManager; +OpenService_t openService; +StartService_t startService; +ControlService_t controlService; +QueryServiceStatus_t queryServiceStatus; +QueryServiceConfig_t queryServiceConfig; +CloseServiceHandle_t closeServiceHandle; + +SC_HANDLE hSCManager; +SC_HANDLE bbs_svc; +SC_HANDLE ftp_svc; +SC_HANDLE web_svc; +SC_HANDLE mail_svc; +SC_HANDLE services_svc; +SERVICE_STATUS bbs_svc_status; +SERVICE_STATUS ftp_svc_status; +SERVICE_STATUS web_svc_status; +SERVICE_STATUS mail_svc_status; +SERVICE_STATUS services_svc_status; +QUERY_SERVICE_CONFIG* bbs_svc_config; +DWORD bbs_svc_config_size; +QUERY_SERVICE_CONFIG* ftp_svc_config; +DWORD ftp_svc_config_size; +QUERY_SERVICE_CONFIG* web_svc_config; +DWORD web_svc_config_size; +QUERY_SERVICE_CONFIG* mail_svc_config; +DWORD mail_svc_config_size; +QUERY_SERVICE_CONFIG* services_svc_config; +DWORD services_svc_config_size; -static void thread_up(BOOL up) +DWORD MaxLogLen=20000; +int threads=1; + +static void thread_up(void* p, BOOL up, BOOL setuid) { char str[128]; static HANDLE mutex; @@ -100,7 +148,7 @@ static void thread_up(BOOL up) int sockets=0; -void socket_open(BOOL open) +void socket_open(void* p, BOOL open) { char str[128]; static HANDLE mutex; @@ -122,14 +170,10 @@ void socket_open(BOOL open) int clients=0; int total_clients=0; -static void client_add(BOOL add) +static void client_add(void* p, BOOL add) { char str[128]; - static HANDLE mutex; - if(!mutex) - mutex=CreateMutex(NULL,false,NULL); - WaitForSingleObject(mutex,INFINITE); if(add) { clients++; total_clients++; @@ -144,10 +188,9 @@ static void client_add(BOOL add) Str=AnsiString(str); if(MainForm->StatusBar->Panels->Items[3]->Text!=Str) MainForm->StatusBar->Panels->Items[3]->Text=Str; - ReleaseMutex(mutex); } -static void client_on(BOOL on, int sock, client_t* client) +static void client_on(void* p, BOOL on, int sock, client_t* client, BOOL update) { char str[128]; int i,j; @@ -165,10 +208,20 @@ static void client_on(BOOL on, int sock, if(ClientForm->ListView->Items->Item[i]->Caption.ToIntDef(0)==sock) break; } - if(i>=ClientForm->ListView->Items->Count) + if(i>=ClientForm->ListView->Items->Count) { + if(update) { /* Can't update a non-existing entry */ + ReleaseMutex(mutex); + ReleaseMutex(ClientForm->ListMutex); + return; + } i=-1; + } - if(on==FALSE) { // Off + if(on) { + if(!update) + client_add(NULL, TRUE); + } else { // Off + client_add(NULL, FALSE); if(i>=0) ClientForm->ListView->Items->Delete(i); ReleaseMutex(mutex); @@ -197,7 +250,7 @@ static void client_on(BOOL on, int sock, ReleaseMutex(ClientForm->ListMutex); } -static int bbs_lputs(char *str) +static int bbs_lputs(void* p, int level, char *str) { static HANDLE mutex; @@ -205,7 +258,7 @@ static int bbs_lputs(char *str) mutex=CreateMutex(NULL,false,NULL); WaitForSingleObject(mutex,INFINITE); - while(TelnetForm->Log->Text.Length()>=MAX_LOGLEN) + while(MaxLogLen && TelnetForm->Log->Text.Length()>=MaxLogLen) TelnetForm->Log->Lines->Delete(0); AnsiString Line=Now().FormatString(LOG_TIME_FMT)+" "; @@ -215,7 +268,7 @@ static int bbs_lputs(char *str) return(Line.Length()); } -static void bbs_status(char *str) +static void bbs_status(void* p, char *str) { static HANDLE mutex; @@ -228,15 +281,11 @@ static void bbs_status(char *str) ReleaseMutex(mutex); } -static void bbs_clients(int clients) +static void bbs_clients(void* p, int clients) { static HANDLE mutex; static save_clients; - if(clients>save_clients) - client_add(TRUE); - else if(clientsCursor=crDefault; MainForm->TelnetStart->Enabled=true; MainForm->TelnetStop->Enabled=false; + MainForm->TelnetRecycle->Enabled=false; + Application->ProcessMessages(); } -static void bbs_started(void) +static void bbs_started(void* p) { Screen->Cursor=crDefault; MainForm->TelnetStart->Enabled=false; MainForm->TelnetStop->Enabled=true; + MainForm->TelnetRecycle->Enabled=true; + Application->ProcessMessages(); } static void bbs_start(void) { Screen->Cursor=crAppStart; - bbs_status("Starting"); - strcpy(MainForm->bbs_startup.ctrl_dir,MainForm->CtrlDirectory.c_str()); + bbs_status(NULL,"Starting"); + SAFECOPY(MainForm->bbs_startup.ctrl_dir + ,MainForm->global.ctrl_dir); + SAFECOPY(MainForm->bbs_startup.temp_dir + ,MainForm->global.temp_dir); + SAFECOPY(MainForm->bbs_startup.host_name + ,MainForm->global.host_name); + MainForm->bbs_startup.sem_chk_freq=MainForm->global.sem_chk_freq; + + /* JavaScript operational parameters */ + MainForm->bbs_startup.js_max_bytes=MainForm->global.js.max_bytes; + MainForm->bbs_startup.js_cx_stack=MainForm->global.js.cx_stack; + MainForm->bbs_startup.js_branch_limit=MainForm->global.js.branch_limit; + MainForm->bbs_startup.js_gc_interval=MainForm->global.js.gc_interval; + MainForm->bbs_startup.js_yield_interval=MainForm->global.js.yield_interval; + _beginthread((void(*)(void*))bbs_thread,0,&MainForm->bbs_startup); + Application->ProcessMessages(); +} + +static int event_lputs(int level, char *str) +{ + static HANDLE mutex; + + if(!mutex) + mutex=CreateMutex(NULL,false,NULL); + WaitForSingleObject(mutex,INFINITE); + + while(MaxLogLen && EventsForm->Log->Text.Length()>=MaxLogLen) + EventsForm->Log->Lines->Delete(0); + + AnsiString Line=Now().FormatString(LOG_TIME_FMT)+" "; + Line+=AnsiString(str).Trim(); + EventsForm->Log->Lines->Add(Line); + ReleaseMutex(mutex); + return(Line.Length()); +} + +static int service_lputs(void* p, int level, char *str) +{ + static HANDLE mutex; + + if(!mutex) + mutex=CreateMutex(NULL,false,NULL); + WaitForSingleObject(mutex,INFINITE); + + while(MaxLogLen && ServicesForm->Log->Text.Length()>=MaxLogLen) + ServicesForm->Log->Lines->Delete(0); + + AnsiString Line=Now().FormatString(LOG_TIME_FMT)+" "; + Line+=AnsiString(str).Trim(); + ServicesForm->Log->Lines->Add(Line); + ReleaseMutex(mutex); + return(Line.Length()); } -static int mail_lputs(char *str) +static void services_status(void* p, char *str) +{ + static HANDLE mutex; + + if(!mutex) + mutex=CreateMutex(NULL,false,NULL); + WaitForSingleObject(mutex,INFINITE); + + ServicesForm->Status->Caption=AnsiString(str); + + ReleaseMutex(mutex); +} + +static void services_terminated(void* p, int code) +{ + Screen->Cursor=crDefault; + MainForm->ServicesStart->Enabled=true; + MainForm->ServicesStop->Enabled=false; + MainForm->ServicesRecycle->Enabled=false; + Application->ProcessMessages(); +} +static void services_started(void* p) +{ + Screen->Cursor=crDefault; + MainForm->ServicesStart->Enabled=false; + MainForm->ServicesStop->Enabled=true; + MainForm->ServicesRecycle->Enabled=true; + Application->ProcessMessages(); +} + +static void services_clients(void* p, int clients) +{ +} + +static int mail_lputs(void* p, int level, char *str) { static HANDLE mutex; static FILE* LogStream; @@ -288,7 +426,7 @@ static int mail_lputs(char *str) return(0); } - while(MailForm->Log->Text.Length()>=MAX_LOGLEN) + while(MaxLogLen && MailForm->Log->Text.Length()>=MaxLogLen) MailForm->Log->Lines->Delete(0); AnsiString Line=Now().FormatString(LOG_TIME_FMT)+" "; @@ -309,7 +447,7 @@ static int mail_lputs(char *str) } } if(LogStream==NULL) - LogStream=fopen(LogFileName.c_str(),"a"); + LogStream=_fsopen(LogFileName.c_str(),"a",SH_DENYNONE); if(LogStream!=NULL) { Line=Now().FormatString("hh:mm:ss")+" "; @@ -323,7 +461,7 @@ static int mail_lputs(char *str) return(Line.Length()); } -static void mail_status(char *str) +static void mail_status(void* p, char *str) { static HANDLE mutex; @@ -336,16 +474,9 @@ static void mail_status(char *str) ReleaseMutex(mutex); } -static void mail_clients(int clients) +static void mail_clients(void* p, int clients) { static HANDLE mutex; - static save_clients; - - if(clients>save_clients) - client_add(TRUE); - else if(clientsCursor=crDefault; MainForm->MailStart->Enabled=true; MainForm->MailStop->Enabled=false; + MainForm->MailRecycle->Enabled=false; + Application->ProcessMessages(); } -static void mail_started(void) +static void mail_started(void* p) { Screen->Cursor=crDefault; MainForm->MailStart->Enabled=false; MainForm->MailStop->Enabled=true; + MainForm->MailRecycle->Enabled=true; + Application->ProcessMessages(); } static void mail_start(void) { Screen->Cursor=crAppStart; - mail_status("Starting"); - strcpy(MainForm->mail_startup.ctrl_dir,MainForm->CtrlDirectory.c_str()); + mail_status(NULL, "Starting"); + SAFECOPY(MainForm->mail_startup.ctrl_dir + ,MainForm->global.ctrl_dir); + SAFECOPY(MainForm->mail_startup.host_name + ,MainForm->global.host_name); + MainForm->mail_startup.sem_chk_freq=MainForm->global.sem_chk_freq; _beginthread((void(*)(void*))mail_server,0,&MainForm->mail_startup); + Application->ProcessMessages(); } -static int ftp_lputs(char *str) +static int ftp_lputs(void* p, int level, char *str) { static HANDLE mutex; static FILE* LogStream; @@ -394,7 +534,7 @@ static int ftp_lputs(char *str) return(0); } - while(FtpForm->Log->Text.Length()>=MAX_LOGLEN) + while(MaxLogLen && FtpForm->Log->Text.Length()>=MaxLogLen) FtpForm->Log->Lines->Delete(0); AnsiString Line=Now().FormatString(LOG_TIME_FMT)+" "; @@ -416,7 +556,7 @@ static int ftp_lputs(char *str) } } if(LogStream==NULL) - LogStream=fopen(LogFileName.c_str(),"a"); + LogStream=_fsopen(LogFileName.c_str(),"a",SH_DENYNONE); if(LogStream!=NULL) { Line=Now().FormatString("hh:mm:ss")+" "; @@ -430,7 +570,7 @@ static int ftp_lputs(char *str) return(Line.Length()); } -static void ftp_status(char *str) +static void ftp_status(void* p, char *str) { static HANDLE mutex; @@ -443,16 +583,9 @@ static void ftp_status(char *str) ReleaseMutex(mutex); } -static void ftp_clients(int clients) +static void ftp_clients(void* p, int clients) { static HANDLE mutex; - static save_clients; - - if(clients>save_clients) - client_add(TRUE); - else if(clientsCursor=crDefault; MainForm->FtpStart->Enabled=true; MainForm->FtpStop->Enabled=false; + MainForm->FtpRecycle->Enabled=false; + Application->ProcessMessages(); } -static void ftp_started(void) +static void ftp_started(void* p) { Screen->Cursor=crDefault; MainForm->FtpStart->Enabled=false; MainForm->FtpStop->Enabled=true; + MainForm->FtpRecycle->Enabled=true; + Application->ProcessMessages(); } static void ftp_start(void) { Screen->Cursor=crAppStart; - ftp_status("Starting"); - strcpy(MainForm->ftp_startup.ctrl_dir,MainForm->CtrlDirectory.c_str()); + ftp_status(NULL, "Starting"); + SAFECOPY(MainForm->ftp_startup.ctrl_dir + ,MainForm->global.ctrl_dir); + SAFECOPY(MainForm->ftp_startup.temp_dir + ,MainForm->global.temp_dir); + SAFECOPY(MainForm->ftp_startup.host_name + ,MainForm->global.host_name); + MainForm->ftp_startup.sem_chk_freq=MainForm->global.sem_chk_freq; + + /* JavaScript operational parameters */ + MainForm->ftp_startup.js_max_bytes=MainForm->global.js.max_bytes; + MainForm->ftp_startup.js_cx_stack=MainForm->global.js.cx_stack; + _beginthread((void(*)(void*))ftp_server,0,&MainForm->ftp_startup); + Application->ProcessMessages(); } //--------------------------------------------------------------------------- +static int web_lputs(void* p, int level, char *str) +{ + static HANDLE mutex; + static FILE* LogStream; + + if(!mutex) + mutex=CreateMutex(NULL,false,NULL); + WaitForSingleObject(mutex,INFINITE); + + if(str==NULL) { + if(LogStream!=NULL) + fclose(LogStream); + LogStream=NULL; + ReleaseMutex(mutex); + return(0); + } + + while(MaxLogLen && WebForm->Log->Text.Length()>=MaxLogLen) + WebForm->Log->Lines->Delete(0); + + AnsiString Line=Now().FormatString(LOG_TIME_FMT)+" "; + Line+=AnsiString(str).Trim(); + WebForm->Log->Lines->Add(Line); +#if 0 + if(MainForm->WebLogFile && MainForm->WebStop->Enabled) { + AnsiString LogFileName + =AnsiString(MainForm->cfg.data_dir) + +"LOGS\\FS" + +Now().FormatString("mmddyy") + +".LOG"; + + if(!FileExists(LogFileName)) { + FileClose(FileCreate(LogFileName)); + if(LogStream!=NULL) { + fclose(LogStream); + LogStream=NULL; + } + } + if(LogStream==NULL) + LogStream=_fsopen(LogFileName.c_str(),"a",SH_DENYNONE); + + if(LogStream!=NULL) { + Line=Now().FormatString("hh:mm:ss")+" "; + Line+=AnsiString(str).Trim(); + Line+="\n"; + fwrite(AnsiString(Line).c_str(),1,Line.Length(),LogStream); + } + } +#endif + ReleaseMutex(mutex); + return(Line.Length()); +} + +static void web_status(void* p, char *str) +{ + static HANDLE mutex; + + if(!mutex) + mutex=CreateMutex(NULL,false,NULL); + WaitForSingleObject(mutex,INFINITE); + + WebForm->Status->Caption=AnsiString(str); + + ReleaseMutex(mutex); +} + +static void web_clients(void* p, int clients) +{ + static HANDLE mutex; + + if(!mutex) + mutex=CreateMutex(NULL,false,NULL); + WaitForSingleObject(mutex,INFINITE); + + WebForm->ProgressBar->Max=MainForm->ftp_startup.max_clients; + WebForm->ProgressBar->Position=clients; -#define REG_KEY "\\Software\\Swindell\\Synchronet Control Panel\\" + ReleaseMutex(mutex); +} +static void web_terminated(void* p, int code) +{ + Screen->Cursor=crDefault; + MainForm->WebStart->Enabled=true; + MainForm->WebStop->Enabled=false; + MainForm->WebRecycle->Enabled=false; + Application->ProcessMessages(); +} +static void web_started(void* p) +{ + Screen->Cursor=crDefault; + MainForm->WebStart->Enabled=false; + MainForm->WebStop->Enabled=true; + MainForm->WebRecycle->Enabled=true; + Application->ProcessMessages(); +} +static void web_start(void) +{ + Screen->Cursor=crAppStart; + web_status(NULL, "Starting"); + SAFECOPY(MainForm->web_startup.ctrl_dir + ,MainForm->global.ctrl_dir); + SAFECOPY(MainForm->web_startup.host_name + ,MainForm->global.host_name); + MainForm->web_startup.sem_chk_freq=MainForm->global.sem_chk_freq; + + /* JavaScript operational parameters */ + MainForm->web_startup.js_max_bytes=MainForm->global.js.max_bytes; + MainForm->web_startup.js_cx_stack=MainForm->global.js.cx_stack; + + _beginthread((void(*)(void*))web_server,0,&MainForm->web_startup); + Application->ProcessMessages(); +} +//--------------------------------------------------------------------------- +/* Server recycle callback (read relevant startup .ini file section) */ +static void recycle(void* cbdata) +{ + char str[MAX_PATH*2]; + FILE* fp=NULL; + bbs_startup_t* bbs=NULL; + ftp_startup_t* ftp=NULL; + web_startup_t* web=NULL; + mail_startup_t* mail=NULL; + services_startup_t* services=NULL; + + SAFEPRINTF(str,"Reading %s",MainForm->ini_file); + if(cbdata==(void*)&MainForm->bbs_startup) { + bbs=&MainForm->bbs_startup; + bbs_lputs(cbdata,LOG_INFO,str); + } else if(cbdata==(void*)&MainForm->ftp_startup) { + ftp=&MainForm->ftp_startup; + ftp_lputs(cbdata,LOG_INFO,str); + } else if(cbdata==(void*)&MainForm->web_startup) { + web=&MainForm->web_startup; + web_lputs(cbdata,LOG_INFO,str); + } else if(cbdata==(void*)&MainForm->mail_startup) { + mail=&MainForm->mail_startup; + mail_lputs(cbdata,LOG_INFO,str); + } else if(cbdata==(void*)&MainForm->services_startup) { + services=&MainForm->services_startup; + service_lputs(cbdata,LOG_INFO,str); + } + + fp=fopen(MainForm->ini_file,"r"); + sbbs_read_ini(fp + ,&MainForm->global + ,NULL ,bbs + ,NULL ,ftp + ,NULL ,web + ,NULL ,mail + ,NULL ,services + ); + if(fp!=NULL) + fclose(fp); +} //--------------------------------------------------------------------------- __fastcall TMainForm::TMainForm(TComponent* Owner) : TForm(Owner) { - CtrlDirectory="c:\\sbbs\\ctrl\\"; - LoginCommand="start telnet://localhost"; - ConfigCommand="%sSCFG %s /T2"; - + /* Defaults */ + SAFECOPY(global.ctrl_dir,"c:\\sbbs\\ctrl\\"); + global.js.max_bytes=JAVASCRIPT_MAX_BYTES; + global.js.cx_stack=JAVASCRIPT_CONTEXT_STACK; + global.js.branch_limit=JAVASCRIPT_BRANCH_LIMIT; + global.js.gc_interval=JAVASCRIPT_GC_INTERVAL; + global.js.yield_interval=JAVASCRIPT_YIELD_INTERVAL; + global.sem_chk_freq=5; /* seconds */ + + /* These are SBBSCTRL-specific */ + LoginCommand="telnet://localhost"; + ConfigCommand="%sscfg.exe %s -l25"; + MinimizeToSysTray=false; + UndockableForms=false; + UseFileAssociations=true; + Initialized=false; + + char* p; + if((p=getenv("SBBSCTRL"))!=NULL) + SAFECOPY(global.ctrl_dir,p); + p=lastchar(global.ctrl_dir); + if(*p!='/' && *p!='\\') + strcat(global.ctrl_dir,"\\"); + memset(&bbs_startup,0,sizeof(bbs_startup)); bbs_startup.size=sizeof(bbs_startup); + bbs_startup.cbdata=&bbs_startup; bbs_startup.first_node=1; bbs_startup.last_node=4; - bbs_startup.telnet_port=IPPORT_TELNET; + bbs_startup.options=BBS_OPT_XTRN_MINIMIZED|BBS_OPT_SYSOP_AVAILABLE; + bbs_startup.telnet_port=IPPORT_TELNET; bbs_startup.telnet_interface=INADDR_ANY; bbs_startup.rlogin_port=513; bbs_startup.rlogin_interface=INADDR_ANY; @@ -507,13 +830,16 @@ __fastcall TMainForm::TMainForm(TCompone bbs_startup.status=bbs_status; bbs_startup.clients=bbs_clients; bbs_startup.started=bbs_started; + bbs_startup.recycle=recycle; bbs_startup.terminated=bbs_terminated; bbs_startup.thread_up=thread_up; bbs_startup.client_on=client_on; bbs_startup.socket_open=socket_open; + bbs_startup.event_lputs=event_lputs; memset(&mail_startup,0,sizeof(mail_startup)); mail_startup.size=sizeof(mail_startup); + mail_startup.cbdata=&mail_startup; mail_startup.smtp_port=IPPORT_SMTP; mail_startup.relay_port=IPPORT_SMTP; mail_startup.pop3_port=110; @@ -522,28 +848,72 @@ __fastcall TMainForm::TMainForm(TCompone mail_startup.status=mail_status; mail_startup.clients=mail_clients; mail_startup.started=mail_started; + mail_startup.recycle=recycle; mail_startup.terminated=mail_terminated; mail_startup.options=MAIL_OPT_ALLOW_POP3; mail_startup.thread_up=thread_up; mail_startup.client_on=client_on; mail_startup.socket_open=socket_open; - mail_startup.max_delivery_attempts=10; - mail_startup.rescan_frequency=300; /* 5 minutes */ + mail_startup.max_delivery_attempts=50; + mail_startup.rescan_frequency=3600; /* 60 minutes */ + mail_startup.lines_per_yield=10; + mail_startup.max_clients=10; + mail_startup.max_msg_size=10*1024*1024; memset(&ftp_startup,0,sizeof(ftp_startup)); ftp_startup.size=sizeof(ftp_startup); + ftp_startup.cbdata=&ftp_startup; ftp_startup.port=IPPORT_FTP; ftp_startup.interface_addr=INADDR_ANY; ftp_startup.lputs=ftp_lputs; ftp_startup.status=ftp_status; ftp_startup.clients=ftp_clients; ftp_startup.started=ftp_started; + ftp_startup.recycle=recycle; ftp_startup.terminated=ftp_terminated; ftp_startup.thread_up=thread_up; ftp_startup.client_on=client_on; ftp_startup.socket_open=socket_open; - ftp_startup.options=FTP_OPT_INDEX_FILE|FTP_OPT_ALLOW_QWK; + ftp_startup.options + =FTP_OPT_INDEX_FILE|FTP_OPT_HTML_INDEX_FILE|FTP_OPT_ALLOW_QWK; + ftp_startup.max_clients=10; strcpy(ftp_startup.index_file_name,"00index"); + strcpy(ftp_startup.html_index_file,"00index.html"); + strcpy(ftp_startup.html_index_script,"ftp-html.js"); + + memset(&web_startup,0,sizeof(web_startup)); + web_startup.size=sizeof(web_startup); + web_startup.cbdata=&web_startup; + web_startup.lputs=web_lputs; + web_startup.status=web_status; + web_startup.clients=web_clients; + web_startup.started=web_started; + web_startup.recycle=recycle; + web_startup.terminated=web_terminated; + web_startup.thread_up=thread_up; + web_startup.client_on=client_on; + web_startup.socket_open=socket_open; + + memset(&services_startup,0,sizeof(services_startup)); + services_startup.size=sizeof(services_startup); + services_startup.cbdata=&services_startup; + services_startup.interface_addr=INADDR_ANY; + services_startup.lputs=service_lputs; + services_startup.status=services_status; + services_startup.clients=services_clients; + services_startup.started=services_started; + services_startup.recycle=recycle; + services_startup.terminated=services_terminated; + services_startup.thread_up=thread_up; + services_startup.client_on=client_on; + services_startup.socket_open=socket_open; + + bbs_log=INVALID_HANDLE_VALUE; + event_log=INVALID_HANDLE_VALUE; + ftp_log=INVALID_HANDLE_VALUE; + web_log=INVALID_HANDLE_VALUE; + mail_log=INVALID_HANDLE_VALUE; + services_log=INVALID_HANDLE_VALUE; /* Default local "Spy Terminal" settings */ SpyTerminalFont=new TFont; @@ -553,6 +923,38 @@ __fastcall TMainForm::TMainForm(TCompone SpyTerminalWidth=434; SpyTerminalHeight=365; SpyTerminalKeyboardActive=true; + + Application->OnMinimize=FormMinimize; + + /* Get pointers to NT Service functions */ + HANDLE hSCMlib = LoadLibrary("ADVAPI32.DLL"); + if(hSCMlib!=NULL) { + openSCManager=(OpenSCManager_t)GetProcAddress(hSCMlib, "OpenSCManagerA"); + openService=(OpenService_t)GetProcAddress(hSCMlib,"OpenServiceA"); + startService=(StartService_t)GetProcAddress(hSCMlib,"StartServiceA"); + controlService=(ControlService_t)GetProcAddress(hSCMlib,"ControlService"); + queryServiceStatus=(QueryServiceStatus_t)GetProcAddress(hSCMlib,"QueryServiceStatus"); + queryServiceConfig=(QueryServiceConfig_t)GetProcAddress(hSCMlib,"QueryServiceConfigA"); + closeServiceHandle=(CloseServiceHandle_t)GetProcAddress(hSCMlib,"CloseServiceHandle"); + FreeLibrary(hSCMlib); + } + + /* Open Service Manager */ + if(openSCManager!=NULL) + hSCManager = openSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_ALL_ACCESS // access required + ); + + /* Open Synchronet Services */ + if(hSCManager!=NULL) { + bbs_svc = openService(hSCManager, NTSVC_NAME_BBS, SERVICE_ALL_ACCESS); + ftp_svc = openService(hSCManager, NTSVC_NAME_FTP, SERVICE_ALL_ACCESS); + web_svc = openService(hSCManager, NTSVC_NAME_WEB, SERVICE_ALL_ACCESS); + mail_svc = openService(hSCManager, NTSVC_NAME_MAIL, SERVICE_ALL_ACCESS); + services_svc = openService(hSCManager, NTSVC_NAME_SERVICES, SERVICE_ALL_ACCESS); + } } //--------------------------------------------------------------------------- void __fastcall TMainForm::FileExitMenuItemClick(TObject *Sender) @@ -564,12 +966,14 @@ void __fastcall TMainForm::FormCreate(TO Height=400; // Just incase we mess it up in the IDE Width=700; - if(putenv("TZ=UCT0")) { - Application->MessageBox("Error settings timezone" - ,"ERROR",MB_OK|MB_ICONEXCLAMATION); + // Verify SBBS.DLL version + long bbs_ver = bbs_ver_num(); + if(bbs_ver < (0x31200 | 'A'-'A') || bbs_ver > (0x399<<8)) { + char str[128]; + sprintf(str,"Incorrect SBBS.DLL Version (%lX)",bbs_ver); + Application->MessageBox(str,"ERROR",MB_OK|MB_ICONEXCLAMATION); Application->Terminate(); } - tzset(); // Read Registry keys TRegistry* Registry=new TRegistry; @@ -577,6 +981,7 @@ void __fastcall TMainForm::FormCreate(TO Application->MessageBox("Error opening registry key" ,REG_KEY,MB_OK|MB_ICONEXCLAMATION); Application->Terminate(); + return; } if(Registry->ValueExists("MainFormTop")) Top=Registry->ReadInteger("MainFormTop"); @@ -588,7 +993,6 @@ void __fastcall TMainForm::FormCreate(TO Width=Registry->ReadInteger("MainFormWidth"); else WindowState=wsMaximized; // Default to fullscreen - if(Registry->ValueExists("SpyTerminalWidth")) SpyTerminalWidth=Registry->ReadInteger("SpyTerminalWidth"); if(Registry->ValueExists("SpyTerminalHeight")) @@ -613,165 +1017,50 @@ void __fastcall TMainForm::FormShow(TObj void __fastcall TMainForm::ViewToolbarMenuItemClick(TObject *Sender) { - Toolbar->Visible=!ViewToolbarMenuItem->Checked; - ViewToolbarMenuItem->Checked=Toolbar->Visible; + Toolbar->Visible=ViewToolbarMenuItem->Checked; } //--------------------------------------------------------------------------- void __fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action) { - SaveSettings(Sender); -} -//--------------------------------------------------------------------------- -void __fastcall TMainForm::SaveSettings(TObject* Sender) -{ - // Write Registry keys - TRegistry* Registry=new TRegistry; - if(!Registry->OpenKey(REG_KEY,true)) { - Application->MessageBox("Error creating registry key" - ,REG_KEY,MB_OK|MB_ICONEXCLAMATION); - Application->Terminate(); - } - - Registry->WriteInteger("MainFormTop",Top); - Registry->WriteInteger("MainFormLeft",Left); - Registry->WriteInteger("MainFormHeight",Height); - Registry->WriteInteger("MainFormWidth",Width); - - Registry->WriteInteger("NodeFormTop",NodeForm->Top); - Registry->WriteInteger("NodeFormLeft",NodeForm->Left); - Registry->WriteInteger("NodeFormHeight",NodeForm->Height); - Registry->WriteInteger("NodeFormWidth",NodeForm->Width); - - Registry->WriteInteger("StatsFormTop",StatsForm->Top); - Registry->WriteInteger("StatsFormLeft",StatsForm->Left); - Registry->WriteInteger("StatsFormHeight",StatsForm->Height); - Registry->WriteInteger("StatsFormWidth",StatsForm->Width); - - Registry->WriteInteger("ClientFormTop",ClientForm->Top); - Registry->WriteInteger("ClientFormLeft",ClientForm->Left); - Registry->WriteInteger("ClientFormHeight",ClientForm->Height); - Registry->WriteInteger("ClientFormWidth",ClientForm->Width); - - Registry->WriteInteger("TelnetFormTop",TelnetForm->Top); - Registry->WriteInteger("TelnetFormLeft",TelnetForm->Left); - Registry->WriteInteger("TelnetFormHeight",TelnetForm->Height); - Registry->WriteInteger("TelnetFormWidth",TelnetForm->Width); - - Registry->WriteInteger("FtpFormTop",FtpForm->Top); - Registry->WriteInteger("FtpFormLeft",FtpForm->Left); - Registry->WriteInteger("FtpFormHeight",FtpForm->Height); - Registry->WriteInteger("FtpFormWidth",FtpForm->Width); - - Registry->WriteInteger("MailFormTop",MailForm->Top); - Registry->WriteInteger("MailFormLeft",MailForm->Left); - Registry->WriteInteger("MailFormHeight",MailForm->Height); - Registry->WriteInteger("MailFormWidth",MailForm->Width); - - Registry->WriteInteger("TopPanelHeight",TopPanel->Height); - Registry->WriteInteger("UpperLeftPageControlWidth" - ,UpperLeftPageControl->Width); - Registry->WriteInteger("LowerLeftPageControlWidth" - ,LowerLeftPageControl->Width); - - Registry->WriteBool("TelnetFormFloating",TelnetForm->Floating); - Registry->WriteBool("NodeFormFloating",NodeForm->Floating); - Registry->WriteBool("StatsFormFloating",StatsForm->Floating); - Registry->WriteBool("ClientFormFloating",ClientForm->Floating); - Registry->WriteBool("FtpFormFloating",FtpForm->Floating); - Registry->WriteBool("MailFormFloating",MailForm->Floating); - - Registry->WriteInteger("TelnetFormPage" - ,PageNum((TPageControl*)TelnetForm->HostDockSite)); - Registry->WriteInteger("NodeFormPage" - ,PageNum((TPageControl*)NodeForm->HostDockSite)); - Registry->WriteInteger("MailFormPage" - ,PageNum((TPageControl*)MailForm->HostDockSite)); - Registry->WriteInteger("FtpFormPage" - ,PageNum((TPageControl*)FtpForm->HostDockSite)); - Registry->WriteInteger("StatsFormPage" - ,PageNum((TPageControl*)StatsForm->HostDockSite)); - Registry->WriteInteger("ClientFormPage" - ,PageNum((TPageControl*)ClientForm->HostDockSite)); - - Registry->WriteBool("ToolBarVisible",Toolbar->Visible); - Registry->WriteBool("StatusBarVisible",StatusBar->Visible); - - Registry->WriteString("CtrlDirectory",CtrlDirectory); - Registry->WriteString("LoginCommand",LoginCommand); - Registry->WriteString("ConfigCommand",ConfigCommand); - - Registry->WriteInteger("SysAutoStart",SysAutoStart); - Registry->WriteInteger("MailAutoStart",MailAutoStart); - Registry->WriteInteger("FtpAutoStart",FtpAutoStart); - Registry->WriteInteger("MailLogFile",MailLogFile); - Registry->WriteInteger("FtpLogFile",FtpLogFile); - - Registry->WriteInteger("TelnetInterface",bbs_startup.telnet_interface); - Registry->WriteInteger("RLoginInterface",bbs_startup.rlogin_interface); - - Registry->WriteInteger("TelnetPort",bbs_startup.telnet_port); - Registry->WriteInteger("RLoginPort",bbs_startup.rlogin_port); - Registry->WriteInteger("FirstNode",bbs_startup.first_node); - Registry->WriteInteger("LastNode",bbs_startup.last_node); - - Registry->WriteString("AnswerSound",AnsiString(bbs_startup.answer_sound)); - Registry->WriteString("HangupSound",AnsiString(bbs_startup.hangup_sound)); - - Registry->WriteInteger("StartupOptions",bbs_startup.options); - - Registry->WriteInteger("MailMaxClients",mail_startup.max_clients); - Registry->WriteInteger("MailMaxInactivity",mail_startup.max_inactivity); - Registry->WriteInteger("MailInterface",mail_startup.interface_addr); - Registry->WriteInteger("MailMaxDeliveryAttempts" - ,mail_startup.max_delivery_attempts); - Registry->WriteInteger("MailRescanFrequency" - ,mail_startup.rescan_frequency); - - Registry->WriteInteger("MailSMTPPort",mail_startup.smtp_port); - Registry->WriteInteger("MailPOP3Port",mail_startup.pop3_port); - - Registry->WriteString("MailRelayServer",mail_startup.relay_server); - Registry->WriteString("MailDNSServer",mail_startup.dns_server); - - Registry->WriteString("MailInboundSound",AnsiString(mail_startup.inbound_sound)); - Registry->WriteString("MailOutboundSound",AnsiString(mail_startup.outbound_sound)); - Registry->WriteInteger("MailOptions",mail_startup.options); - - Registry->WriteString("MailPOP3Sound",AnsiString(mail_startup.pop3_sound)); - - Registry->WriteInteger("FtpPort",ftp_startup.port); - Registry->WriteInteger("FtpMaxClients",ftp_startup.max_clients); - Registry->WriteInteger("FtpMaxInactivity",ftp_startup.max_inactivity); - Registry->WriteInteger("FtpInterface",ftp_startup.interface_addr); - Registry->WriteString("FtpAnswerSound",AnsiString(ftp_startup.answer_sound)); - Registry->WriteString("FtpHangupSound",AnsiString(ftp_startup.hangup_sound)); - Registry->WriteString("FtpIndexFileName" - ,AnsiString(ftp_startup.index_file_name)); - Registry->WriteInteger("FtpOptions",ftp_startup.options); - - Registry->WriteInteger( "SpyTerminalWidth" - ,SpyTerminalWidth); - Registry->WriteInteger( "SpyTerminalHeight" - ,SpyTerminalHeight); - Registry->WriteString( "SpyTerminalFontName" - ,SpyTerminalFont->Name); - Registry->WriteInteger( "SpyTerminalFontSize" - ,SpyTerminalFont->Size); - Registry->WriteBool( "SpyTerminalKeyboardActive" - ,SpyTerminalKeyboardActive); - - Registry->CloseKey(); - delete Registry; + UpTimer->Enabled=false; /* Stop updating the status bar */ + if(TrayIcon->Visible) /* minimized to tray? */ + TrayIcon->Visible=false; /* restore to avoid crash */ + + /* This is necessary to save form sizes/positions */ + if(Initialized) /* Don't overwrite registry settings with defaults */ + SaveRegistrySettings(Sender); + + StatusBar->Panels->Items[4]->Text="Closing..."; + time_t start=time(NULL); + while( (bbs_svc==NULL && TelnetStop->Enabled) + || (mail_svc==NULL && MailStop->Enabled) + || (ftp_svc==NULL && FtpStop->Enabled) + || (web_svc==NULL && WebStop->Enabled) + || (services_svc==NULL && ServicesStop->Enabled)) { + if(time(NULL)-start>30) + break; + Application->ProcessMessages(); + YIELD(); + } + /* Extra time for callbacks to be called by child threads */ + start=time(NULL); + while(time(NULL)ProcessMessages(); + YIELD(); + } +#if 0 + if(hSCManager!=NULL) + closeServiceHandle(hSCManager); +#endif } //--------------------------------------------------------------------------- void __fastcall TMainForm::FormCloseQuery(TObject *Sender, bool &CanClose) { - CanClose=true; + CanClose=false; - if(TelnetStop->Enabled) { - CanClose=false; + if(TelnetStop->Enabled && bbs_svc==NULL) { if(TelnetForm->ProgressBar->Position && Application->MessageBox("Shut down the Telnet Server?" ,"Telnet Server In Use", MB_OKCANCEL)!=IDOK) @@ -779,8 +1068,7 @@ void __fastcall TMainForm::FormCloseQuer TelnetStopExecute(Sender); } - if(MailStop->Enabled) { - CanClose=false; + if(MailStop->Enabled && mail_svc==NULL) { if(MailForm->ProgressBar->Position && Application->MessageBox("Shut down the Mail Server?" ,"Mail Server In Use", MB_OKCANCEL)!=IDOK) @@ -788,8 +1076,7 @@ void __fastcall TMainForm::FormCloseQuer MailStopExecute(Sender); } - if(FtpStop->Enabled) { - CanClose=false; + if(FtpStop->Enabled && ftp_svc==NULL) { if(FtpForm->ProgressBar->Position && Application->MessageBox("Shut down the FTP Server?" ,"FTP Server In Use", MB_OKCANCEL)!=IDOK) @@ -797,30 +1084,116 @@ void __fastcall TMainForm::FormCloseQuer FtpStopExecute(Sender); } - if(CanClose==false) - CloseTimer->Enabled=true; + if(WebStop->Enabled && web_svc==NULL) { + if(WebForm->ProgressBar->Position + && Application->MessageBox("Shut down the Web Server?" + ,"Web Server In Use", MB_OKCANCEL)!=IDOK) + return; + WebStopExecute(Sender); + } + + if(ServicesStop->Enabled && services_svc==NULL) + ServicesStopExecute(Sender); + + CanClose=true; +} +//--------------------------------------------------------------------------- +BOOL StartNTsvc(SC_HANDLE svc, SERVICE_STATUS* status, QUERY_SERVICE_CONFIG* config, DWORD config_size) +{ + if(svc==NULL || startService==NULL || queryServiceStatus==NULL || config==NULL) + return(FALSE); + + DWORD ret; + if(!queryServiceConfig(svc,config,config_size,&ret)) + return(FALSE); + if(config->dwStartType==SERVICE_DISABLED) + return(FALSE); + if(!queryServiceStatus(svc,status)) + return(FALSE); + if(status->dwCurrentState!=SERVICE_STOPPED) + return(TRUE); + if(!startService(svc,0,NULL)) + Application->MessageBox(AnsiString("ERROR " + IntToStr(GetLastError()) + + " starting " + config->lpDisplayName).c_str() + ,"ERROR" + ,MB_OK|MB_ICONEXCLAMATION); + return(TRUE); } //--------------------------------------------------------------------------- - void __fastcall TMainForm::TelnetStartExecute(TObject *Sender) { - bbs_start(); + if(!StartNTsvc(bbs_svc,&bbs_svc_status,bbs_svc_config,bbs_svc_config_size)) + bbs_start(); +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::ServicesStartExecute(TObject *Sender) +{ + if(StartNTsvc(services_svc,&services_svc_status,services_svc_config,services_svc_config_size)) + return; + Screen->Cursor=crAppStart; + services_status(NULL, "Starting"); + + SAFECOPY(MainForm->services_startup.ctrl_dir + ,MainForm->global.ctrl_dir); + SAFECOPY(MainForm->services_startup.host_name + ,MainForm->global.host_name); + MainForm->services_startup.sem_chk_freq=global.sem_chk_freq; + + /* JavaScript operational parameters */ + MainForm->services_startup.js_max_bytes=MainForm->global.js.max_bytes; + MainForm->services_startup.js_cx_stack=MainForm->global.js.cx_stack; + MainForm->services_startup.js_branch_limit=MainForm->global.js.branch_limit; + MainForm->services_startup.js_gc_interval=MainForm->global.js.gc_interval; + MainForm->services_startup.js_yield_interval=MainForm->global.js.yield_interval; + + _beginthread((void(*)(void*))services_thread,0,&MainForm->services_startup); + Application->ProcessMessages(); +} + +//--------------------------------------------------------------------------- +BOOL StopNTsvc(SC_HANDLE svc, SERVICE_STATUS* status) +{ + if(svc==NULL || controlService==NULL) + return(FALSE); + + return controlService(svc,SERVICE_CONTROL_STOP,status); +} + +//--------------------------------------------------------------------------- + +void __fastcall TMainForm::ServicesStopExecute(TObject *Sender) +{ + if(StopNTsvc(services_svc,&services_svc_status)) + return; + Screen->Cursor=crAppStart; + services_status(NULL, "Terminating"); + services_terminate(); + Application->ProcessMessages(); } //--------------------------------------------------------------------------- void __fastcall TMainForm::TelnetStopExecute(TObject *Sender) { - Screen->Cursor=crAppStart; - bbs_status("Terminating"); - bbs_terminate(); + if(StopNTsvc(bbs_svc,&bbs_svc_status)) + return; + Screen->Cursor=crAppStart; + bbs_status(NULL, "Terminating"); + bbs_terminate(); + Application->ProcessMessages(); } //--------------------------------------------------------------------------- void __fastcall TMainForm::TelnetConfigureExecute(TObject *Sender) { + static inside; + if(inside) return; + inside=true; + Application->CreateForm(__classid(TTelnetCfgDlg), &TelnetCfgDlg); TelnetCfgDlg->ShowModal(); delete TelnetCfgDlg; + + inside=false; } //--------------------------------------------------------------------------- @@ -844,83 +1217,143 @@ void __fastcall TMainForm::NodeListStopE void __fastcall TMainForm::MailConfigureExecute(TObject *Sender) { + static inside; + if(inside) return; + inside=true; + Application->CreateForm(__classid(TMailCfgDlg), &MailCfgDlg); MailCfgDlg->ShowModal(); delete MailCfgDlg; + + inside=false; } //--------------------------------------------------------------------------- void __fastcall TMainForm::MailStartExecute(TObject *Sender) { - mail_start(); + if(!StartNTsvc(mail_svc,&mail_svc_status,mail_svc_config,mail_svc_config_size)) + mail_start(); } //--------------------------------------------------------------------------- void __fastcall TMainForm::MailStopExecute(TObject *Sender) { - Screen->Cursor=crAppStart; - mail_status("Terminating"); - mail_terminate(); + if(StopNTsvc(mail_svc,&mail_svc_status)) + return; + Screen->Cursor=crAppStart; + mail_status(NULL, "Terminating"); + mail_terminate(); + Application->ProcessMessages(); } //--------------------------------------------------------------------------- - void __fastcall TMainForm::ViewTelnetExecute(TObject *Sender) { - TelnetForm->Visible=!TelnetForm->Visible; - ViewTelnet->Checked=TelnetForm->Visible; + TelnetForm->Visible=ViewTelnet->Checked; +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::ViewEventsExecute(TObject *Sender) +{ + EventsForm->Visible=ViewEvents->Checked; } //--------------------------------------------------------------------------- void __fastcall TMainForm::ViewNodesExecute(TObject *Sender) { - NodeForm->Visible=!NodeForm->Visible; - ViewNodes->Checked=NodeForm->Visible; + NodeForm->Visible=ViewNodes->Checked; } //--------------------------------------------------------------------------- void __fastcall TMainForm::ViewMailServerExecute(TObject *Sender) { - MailForm->Visible=!MailForm->Visible; - ViewMailServer->Checked=MailForm->Visible; + MailForm->Visible=ViewMailServer->Checked; } //--------------------------------------------------------------------------- void __fastcall TMainForm::ViewFtpServerExecute(TObject *Sender) { - FtpForm->Visible=!FtpForm->Visible; - ViewFtpServer->Checked=FtpForm->Visible; + FtpForm->Visible=ViewFtpServer->Checked; +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::ViewWebServerExecute(TObject *Sender) +{ + WebForm->Visible=ViewWebServer->Checked; +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::ViewServicesExecute(TObject *Sender) +{ + ServicesForm->Visible=ViewServices->Checked; +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::ViewStatsExecute(TObject *Sender) +{ + StatsForm->Visible=ViewStats->Checked; +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::ViewClientsExecute(TObject *Sender) +{ + ClientForm->Visible=ViewClients->Checked; } //--------------------------------------------------------------------------- - void __fastcall TMainForm::FtpStartExecute(TObject *Sender) { - ftp_start(); + if(!StartNTsvc(ftp_svc,&ftp_svc_status,ftp_svc_config,ftp_svc_config_size)) + ftp_start(); } //--------------------------------------------------------------------------- void __fastcall TMainForm::FtpStopExecute(TObject *Sender) { - Screen->Cursor=crAppStart; - ftp_status("Terminating"); - ftp_terminate(); + if(StopNTsvc(ftp_svc,&ftp_svc_status)) + return; + Screen->Cursor=crAppStart; + ftp_status(NULL, "Terminating"); + ftp_terminate(); + Application->ProcessMessages(); } //--------------------------------------------------------------------------- void __fastcall TMainForm::FtpConfigureExecute(TObject *Sender) { + static inside; + if(inside) return; + inside=true; + Application->CreateForm(__classid(TFtpCfgDlg), &FtpCfgDlg); FtpCfgDlg->ShowModal(); delete FtpCfgDlg; + + inside=false; } //--------------------------------------------------------------------------- - -void __fastcall TMainForm::CloseTimerTimer(TObject *Sender) +void __fastcall TMainForm::WebStartExecute(TObject *Sender) +{ + if(!StartNTsvc(web_svc,&web_svc_status,web_svc_config,web_svc_config_size)) + web_start(); +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::WebStopExecute(TObject *Sender) { - if(!TelnetStop->Enabled && !MailStop->Enabled && !FtpStop->Enabled) - Close(); + if(StopNTsvc(web_svc,&web_svc_status)) + return; + Screen->Cursor=crAppStart; + web_status(NULL, "Terminating"); + web_terminate(); + Application->ProcessMessages(); } //--------------------------------------------------------------------------- +void __fastcall TMainForm::WebConfigureExecute(TObject *Sender) +{ + static inside; + if(inside) return; + inside=true; + + Application->CreateForm(__classid(TWebCfgDlg), &WebCfgDlg); + WebCfgDlg->ShowModal(); + delete WebCfgDlg; + inside=false; +} +//--------------------------------------------------------------------------- void __fastcall TMainForm::BBSConfigureMenuItemClick(TObject *Sender) { char str[256]; @@ -930,18 +1363,22 @@ void __fastcall TMainForm::BBSConfigureM STARTUPINFO startup_info={0}; PROCESS_INFORMATION process_info; startup_info.cb=sizeof(startup_info); + startup_info.lpTitle="Synchronet Configuration Utility"; CreateProcess( NULL, // pointer to name of executable module str, // pointer to command line string NULL, // process security attributes NULL, // thread security attributes - TRUE, // handle inheritance flag + FALSE, // handle inheritance flag CREATE_NEW_CONSOLE|CREATE_SEPARATE_WOW_VDM, // creation flags NULL, // pointer to new environment block cfg.ctrl_dir, // pointer to current directory name &startup_info, // pointer to STARTUPINFO &process_info // pointer to PROCESS_INFORMATION ); + // Resource leak if you don't close these: + CloseHandle(process_info.hThread); + CloseHandle(process_info.hProcess); } //--------------------------------------------------------------------------- @@ -971,74 +1408,19 @@ void __fastcall TMainForm::FtpCloseButto ViewFtpServerExecute(Sender); } //--------------------------------------------------------------------------- - - -#define STAT_DESC_LEN 23 - void __fastcall TMainForm::StatsTimerTick(TObject *Sender) { char str[128]; int i; static stats_t stats; + static users; + static newusers; + static counter; - getstats(&cfg,0,&stats); - -#if 0 - for(i=0;i<8;i++) { - str[0]; - switch(i) { - case 0: - sprintf(str,"%*s %lu Total: %lu" - ,STAT_DESC_LEN,"Logons Today:" - ,stats.ltoday,stats.logons); - break; - case 1: - sprintf(str,"%*s %lu Total: %lu" - ,STAT_DESC_LEN,"Time Used Today:" - ,stats.ttoday,stats.timeon); - break; - case 2: - sprintf(str,"%*s %lu bytes in %lu files" - ,STAT_DESC_LEN,"Uploads Today:" - ,stats.ulb,stats.uls); - break; - case 3: - sprintf(str,"%*s %lu bytes in %lu files" - ,STAT_DESC_LEN,"Downloads Today:" - ,stats.dlb,stats.dls); - break; - case 4: - sprintf(str,"%*s %lu" - ,STAT_DESC_LEN,"Messages Posted Today:" - ,stats.ptoday); - break; - case 5: - sprintf(str,"%*s %lu Total: %lu" - ,STAT_DESC_LEN,"E-mail Sent Today:" - ,stats.etoday,getmail(&cfg,0,0)); - break; - case 6: - sprintf(str,"%*s %lu Total: %lu" - ,STAT_DESC_LEN,"Feedback Sent Today:" - ,stats.ftoday,getmail(&cfg,1,0)); - break; - case 7: - sprintf(str,"%*s %hu Total: %lu" - ,STAT_DESC_LEN,"New Users Today:" - ,stats.nusers,lastuser(&cfg)); - break; - } - if(!str[0]) - break; - - AnsiString Str=AnsiString(str); + if(!StatsForm->Visible) + return; - if(StatsForm->ListBox->Items->CountListBox->Items->Add(Str); - else if(StatsForm->ListBox->Items->Strings[i]!=Str) - StatsForm->ListBox->Items->Strings[i]=str; - } -#else + getstats(&cfg,0,&stats); StatsForm->TotalLogons->Caption=AnsiString(stats.logons); StatsForm->LogonsToday->Caption=AnsiString(stats.ltoday); @@ -1048,8 +1430,11 @@ void __fastcall TMainForm::StatsTimerTic StatsForm->EMailToday->Caption=AnsiString(stats.etoday); StatsForm->TotalFeedback->Caption=AnsiString(getmail(&cfg,1,0)); StatsForm->FeedbackToday->Caption=AnsiString(stats.ftoday); - StatsForm->TotalUsers->Caption=AnsiString(lastuser(&cfg)); - StatsForm->NewUsersToday->Caption=AnsiString(stats.nusers); + /* Don't scan a large user database more often than necessary */ + if(!counter || users<100 || (counter%(users/100))==0 || stats.nusers!=newusers) + users=total_users(&cfg); + StatsForm->TotalUsers->Caption=AnsiString(users); + StatsForm->NewUsersToday->Caption=AnsiString(newusers=stats.nusers); StatsForm->PostsToday->Caption=AnsiString(stats.ptoday); StatsForm->UploadedFiles->Caption=AnsiString(stats.uls); if(stats.ulb>=1024*1024) @@ -1068,17 +1453,9 @@ void __fastcall TMainForm::StatsTimerTic sprintf(str,"%lu",stats.dlb); StatsForm->DownloadedBytes->Caption=AnsiString(str); -#endif + counter++; } //--------------------------------------------------------------------------- - -void __fastcall TMainForm::ViewStatsExecute(TObject *Sender) -{ - StatsForm->Visible=!StatsForm->Visible; - ViewStats->Checked=StatsForm->Visible; -} -//--------------------------------------------------------------------------- - void __fastcall TMainForm::StatsCloseButtonClick(TObject *Sender) { ViewStatsExecute(Sender); @@ -1117,20 +1494,114 @@ int __fastcall TMainForm::PageNum(TPageC return(PAGE_LOWERLEFT); return(PAGE_LOWERRIGHT); } +TColor __fastcall TMainForm::ReadColor(TRegistry* Registry + ,AnsiString name) +{ + if(Registry->ValueExists(name + "Color")) + return(StringToColor(Registry->ReadString(name + "Color"))); + + return(clWindow); // Default +} +void __fastcall TMainForm::WriteColor(TRegistry* Registry + ,AnsiString name, TColor color) +{ + Registry->WriteString(name + "Color", ColorToString(color)); +} + +int FontStyleToInt(TFont* Font) +{ + int style=0; + for(int i=fsBold;i<=fsStrikeOut;i++) + if(Font->Style.Contains((TFontStyle)i)) + style|=(1<Style=Font->Style.Clear(); + for(int i=fsBold;i<=fsStrikeOut;i++) + if(style&(1<Style=Font->Style<<(TFontStyle)i; +} + +void __fastcall TMainForm::ReadFont(AnsiString subkey, TFont* Font) +{ + // Read Registry keys + TRegistry* Registry=new TRegistry; + AnsiString key = REG_KEY + subkey + "Font"; + if(!Registry->OpenKey(key,true)) { + Application->MessageBox("Error opening registry key" + ,key.c_str(),MB_OK|MB_ICONEXCLAMATION); + Application->Terminate(); + return; + } + if(Registry->ValueExists("Name")) + Font->Name=Registry->ReadString("Name"); + if(Registry->ValueExists("Color")) + Font->Color=StringToColor(Registry->ReadString("Color")); + if(Registry->ValueExists("Height")) + Font->Height=Registry->ReadInteger("Height"); + if(Registry->ValueExists("Size")) + Font->Size=Registry->ReadInteger("Size"); + + if(Registry->ValueExists("Style")) + IntToFontStyle(Registry->ReadInteger("Style"),Font); + + Registry->CloseKey(); + delete Registry; +} +void __fastcall TMainForm::WriteFont(AnsiString subkey, TFont* Font) +{ + // Read Registry keys + TRegistry* Registry=new TRegistry; + AnsiString key = REG_KEY + subkey + "Font"; + if(!Registry->OpenKey(key,true)) { + Application->MessageBox("Error opening registry key" + ,key.c_str(),MB_OK|MB_ICONEXCLAMATION); + Application->Terminate(); + return; + } + Registry->WriteString("Name",Font->Name); + Registry->WriteString("Color",ColorToString(Font->Color)); + Registry->WriteInteger("Height",Font->Height); + Registry->WriteInteger("Size",Font->Size); + Registry->WriteInteger("Style",FontStyleToInt(Font)); + + Registry->CloseKey(); + delete Registry; +} void __fastcall TMainForm::StartupTimerTick(TObject *Sender) { bool TelnetFormFloating=false; + bool EventsFormFloating=false; + bool ServicesFormFloating=false; bool NodeFormFloating=false; bool StatsFormFloating=false; bool ClientFormFloating=false; bool MailFormFloating=false; bool FtpFormFloating=false; + bool WebFormFloating=false; int NodeFormPage=PAGE_UPPERLEFT; int StatsFormPage=PAGE_UPPERLEFT; int ClientFormPage=PAGE_UPPERLEFT; int TelnetFormPage=PAGE_LOWERLEFT; + int EventsFormPage=PAGE_LOWERLEFT; int MailFormPage=PAGE_UPPERRIGHT; int FtpFormPage=PAGE_LOWERRIGHT; + int WebFormPage=PAGE_LOWERRIGHT; + int ServicesFormPage=PAGE_LOWERRIGHT; +#if 0 /* not yet working */ + bool TelnetFormVisible=true; + bool EventsFormVisible=true; + bool ServicesFormVisible=true; + bool NodeFormVisible=true; + bool StatsFormVisible=true; + bool ClientFormVisible=true; + bool MailFormVisible=true; + bool FtpFormVisible=true; + bool WebFormVisible=true; +#endif AnsiString Str; @@ -1142,6 +1613,7 @@ void __fastcall TMainForm::StartupTimerT Application->MessageBox("Error opening registry key" ,REG_KEY,MB_OK|MB_ICONEXCLAMATION); Application->Terminate(); + return; } TopPanel->Height=Height/3; @@ -1156,22 +1628,55 @@ void __fastcall TMainForm::StartupTimerT if(Registry->ValueExists("LowerLeftPageControlWidth")) LowerLeftPageControl->Width =Registry->ReadInteger("LowerLeftPageControlWidth"); + if(Registry->ValueExists("UndockableForms")) + UndockableForms=Registry->ReadBool("UndockableForms"); - if(Registry->ValueExists("TelnetFormFloating")) - TelnetFormFloating=Registry->ReadBool("TelnetFormFloating"); - if(Registry->ValueExists("NodeFormFloating")) - NodeFormFloating=Registry->ReadBool("NodeFormFloating"); - if(Registry->ValueExists("StatsFormFloating")) - StatsFormFloating=Registry->ReadBool("StatsFormFloating"); - if(Registry->ValueExists("ClientFormFloating")) - ClientFormFloating=Registry->ReadBool("ClientFormFloating"); - if(Registry->ValueExists("MailFormFloating")) - MailFormFloating=Registry->ReadBool("MailFormFloating"); - if(Registry->ValueExists("FtpFormFloating")) - FtpFormFloating=Registry->ReadBool("FtpFormFloating"); - + if(UndockableForms) { + if(Registry->ValueExists("TelnetFormFloating")) + TelnetFormFloating=Registry->ReadBool("TelnetFormFloating"); + if(Registry->ValueExists("EventsFormFloating")) + EventsFormFloating=Registry->ReadBool("EventsFormFloating"); + if(Registry->ValueExists("ServicesFormFloating")) + ServicesFormFloating=Registry->ReadBool("ServicesFormFloating"); + if(Registry->ValueExists("NodeFormFloating")) + NodeFormFloating=Registry->ReadBool("NodeFormFloating"); + if(Registry->ValueExists("StatsFormFloating")) + StatsFormFloating=Registry->ReadBool("StatsFormFloating"); + if(Registry->ValueExists("ClientFormFloating")) + ClientFormFloating=Registry->ReadBool("ClientFormFloating"); + if(Registry->ValueExists("MailFormFloating")) + MailFormFloating=Registry->ReadBool("MailFormFloating"); + if(Registry->ValueExists("FtpFormFloating")) + FtpFormFloating=Registry->ReadBool("FtpFormFloating"); + if(Registry->ValueExists("WebFormFloating")) + WebFormFloating=Registry->ReadBool("WebFormFloating"); + } +#if 0 + if(Registry->ValueExists("TelnetFormVisible")) + TelnetFormVisible=Registry->ReadBool("TelnetFormVisible"); + if(Registry->ValueExists("EventsFormVisible")) + EventsFormVisible=Registry->ReadBool("EventsFormVisible"); + if(Registry->ValueExists("ServicesFormVisible")) + ServicesFormVisible=Registry->ReadBool("ServicesFormVisible"); + if(Registry->ValueExists("NodeFormVisible")) + NodeFormVisible=Registry->ReadBool("NodeFormVisible"); + if(Registry->ValueExists("StatsFormVisible")) + StatsFormVisible=Registry->ReadBool("StatsFormVisible"); + if(Registry->ValueExists("ClientFormVisible")) + ClientFormVisible=Registry->ReadBool("ClientFormVisible"); + if(Registry->ValueExists("MailFormVisible")) + MailFormVisible=Registry->ReadBool("MailFormVisible"); + if(Registry->ValueExists("FtpFormVisible")) + FtpFormVisible=Registry->ReadBool("FtpFormVisible"); + if(Registry->ValueExists("WebFormVisible")) + WebFormVisible=Registry->ReadBool("WebFormVisible"); +#endif if(Registry->ValueExists("TelnetFormPage")) TelnetFormPage=Registry->ReadInteger("TelnetFormPage"); + if(Registry->ValueExists("EventsFormPage")) + EventsFormPage=Registry->ReadInteger("EventsFormPage"); + if(Registry->ValueExists("ServicesFormPage")) + ServicesFormPage=Registry->ReadInteger("ServicesFormPage"); if(Registry->ValueExists("NodeFormPage")) NodeFormPage=Registry->ReadInteger("NodeFormPage"); if(Registry->ValueExists("StatsFormPage")) @@ -1182,6 +1687,25 @@ void __fastcall TMainForm::StartupTimerT MailFormPage=Registry->ReadInteger("MailFormPage"); if(Registry->ValueExists("FtpFormPage")) FtpFormPage=Registry->ReadInteger("FtpFormPage"); + if(Registry->ValueExists("WebFormPage")) + WebFormPage=Registry->ReadInteger("WebFormPage"); + + TelnetForm->Log->Color=ReadColor(Registry,"TelnetLog"); + ReadFont("TelnetLog",TelnetForm->Log->Font); + EventsForm->Log->Color=ReadColor(Registry,"EventsLog"); + ReadFont("EventsLog",EventsForm->Log->Font); + ServicesForm->Log->Color=ReadColor(Registry,"ServicesLog"); + ReadFont("ServicesLog",ServicesForm->Log->Font); + MailForm->Log->Color=ReadColor(Registry,"MailLog"); + ReadFont("MailLog",MailForm->Log->Font); + FtpForm->Log->Color=ReadColor(Registry,"FtpLog"); + ReadFont("FtpLog",FtpForm->Log->Font); + WebForm->Log->Color=ReadColor(Registry,"WebLog"); + ReadFont("WebLog",WebForm->Log->Font); + NodeForm->ListBox->Color=ReadColor(Registry,"NodeList"); + ReadFont("NodeList",NodeForm->ListBox->Font); + ClientForm->ListView->Color=ReadColor(Registry,"ClientList"); + ReadFont("ClientList",ClientForm->ListView->Font); if(Registry->ValueExists("TelnetFormTop")) TelnetForm->Top=Registry->ReadInteger("TelnetFormTop"); @@ -1192,6 +1716,24 @@ void __fastcall TMainForm::StartupTimerT if(Registry->ValueExists("TelnetFormHeight")) TelnetForm->Height=Registry->ReadInteger("TelnetFormHeight"); + if(Registry->ValueExists("EventsFormTop")) + EventsForm->Top=Registry->ReadInteger("EventsFormTop"); + if(Registry->ValueExists("EventsFormLeft")) + EventsForm->Left=Registry->ReadInteger("EventsFormLeft"); + if(Registry->ValueExists("EventsFormWidth")) + EventsForm->Width=Registry->ReadInteger("EventsFormWidth"); + if(Registry->ValueExists("EventsFormHeight")) + EventsForm->Height=Registry->ReadInteger("EventsFormHeight"); + + if(Registry->ValueExists("ServicesFormTop")) + ServicesForm->Top=Registry->ReadInteger("ServicesFormTop"); + if(Registry->ValueExists("ServicesFormLeft")) + ServicesForm->Left=Registry->ReadInteger("ServicesFormLeft"); + if(Registry->ValueExists("ServicesFormWidth")) + ServicesForm->Width=Registry->ReadInteger("ServicesFormWidth"); + if(Registry->ValueExists("ServicesFormHeight")) + ServicesForm->Height=Registry->ReadInteger("ServicesFormHeight"); + if(Registry->ValueExists("FtpFormTop")) FtpForm->Top=Registry->ReadInteger("FtpFormTop"); if(Registry->ValueExists("FtpFormLeft")) @@ -1201,6 +1743,15 @@ void __fastcall TMainForm::StartupTimerT if(Registry->ValueExists("FtpFormHeight")) FtpForm->Height=Registry->ReadInteger("FtpFormHeight"); + if(Registry->ValueExists("WebFormTop")) + WebForm->Top=Registry->ReadInteger("WebFormTop"); + if(Registry->ValueExists("WebFormLeft")) + WebForm->Left=Registry->ReadInteger("WebFormLeft"); + if(Registry->ValueExists("WebFormWidth")) + WebForm->Width=Registry->ReadInteger("WebFormWidth"); + if(Registry->ValueExists("WebFormHeight")) + WebForm->Height=Registry->ReadInteger("WebFormHeight"); + if(Registry->ValueExists("MailFormTop")) MailForm->Top=Registry->ReadInteger("MailFormTop"); if(Registry->ValueExists("MailFormLeft")) @@ -1237,33 +1788,37 @@ void __fastcall TMainForm::StartupTimerT if(Registry->ValueExists("ClientFormHeight")) ClientForm->Height=Registry->ReadInteger("ClientFormHeight"); + for(int i=0;iListView->Columns->Count;i++) { + char str[128]; + sprintf(str,"ClientListColumn%dWidth",i); + if(Registry->ValueExists(str)) + ClientForm->ListView->Columns->Items[i]->Width + =Registry->ReadInteger(str); + } + if(Registry->ValueExists("ToolbarVisible")) Toolbar->Visible=Registry->ReadBool("ToolbarVisible"); - if(Registry->ValueExists("SysAutoStart")) - SysAutoStart=Registry->ReadInteger("SysAutoStart"); - else - SysAutoStart=true; - - if(Registry->ValueExists("MailAutoStart")) - MailAutoStart=Registry->ReadInteger("MailAutoStart"); - else - MailAutoStart=true; - - if(Registry->ValueExists("FtpAutoStart")) - FtpAutoStart=Registry->ReadInteger("FtpAutoStart"); - else - FtpAutoStart=true; - ViewToolbarMenuItem->Checked=Toolbar->Visible; ViewStatusBarMenuItem->Checked=StatusBar->Visible; - if(Registry->ValueExists("CtrlDirectory")) - CtrlDirectory=Registry->ReadString("CtrlDirectory"); + if(Registry->ValueExists("MaxLogLen")) + MaxLogLen=Registry->ReadInteger("MaxLogLen"); + if(Registry->ValueExists("LoginCommand")) LoginCommand=Registry->ReadString("LoginCommand"); if(Registry->ValueExists("ConfigCommand")) ConfigCommand=Registry->ReadString("ConfigCommand"); + if(Registry->ValueExists("Password")) + Password=Registry->ReadString("Password"); + if(Registry->ValueExists("MinimizeToSysTray")) + MinimizeToSysTray=Registry->ReadBool("MinimizeToSysTray"); + if(Registry->ValueExists("UseFileAssociations")) + UseFileAssociations=Registry->ReadBool("UseFileAssociations"); + if(Registry->ValueExists("NodeDisplayInterval")) + NodeForm->Timer->Interval=Registry->ReadInteger("NodeDisplayInterval")*1000; + if(Registry->ValueExists("ClientDisplayInterval")) + ClientForm->Timer->Interval=Registry->ReadInteger("ClientDisplayInterval")*1000; if(Registry->ValueExists("MailLogFile")) MailLogFile=Registry->ReadInteger("MailLogFile"); @@ -1275,121 +1830,263 @@ void __fastcall TMainForm::StartupTimerT else FtpLogFile=true; - if(Registry->ValueExists("TelnetInterface")) - bbs_startup.telnet_interface=Registry->ReadInteger("TelnetInterface"); - if(Registry->ValueExists("RLoginInterface")) - bbs_startup.rlogin_interface=Registry->ReadInteger("RLoginInterface"); - - if(Registry->ValueExists("TelnetPort")) - bbs_startup.telnet_port=Registry->ReadInteger("TelnetPort"); - if(Registry->ValueExists("RLoginPort")) - bbs_startup.rlogin_port=Registry->ReadInteger("RLoginPort"); - - if(Registry->ValueExists("FirstNode")) - bbs_startup.first_node=Registry->ReadInteger("FirstNode"); - - if(Registry->ValueExists("LastNode")) - bbs_startup.last_node=Registry->ReadInteger("LastNode"); - - if(Registry->ValueExists("AnswerSound")) - sprintf(bbs_startup.answer_sound,"%.*s" - ,sizeof(bbs_startup.answer_sound)-1 - ,Registry->ReadString("AnswerSound").c_str()); - - if(Registry->ValueExists("HangupSound")) - sprintf(bbs_startup.hangup_sound,"%.*s" - ,sizeof(bbs_startup.hangup_sound)-1 - ,Registry->ReadString("HangupSound").c_str()); - - if(Registry->ValueExists("StartupOptions")) - bbs_startup.options=Registry->ReadInteger("StartupOptions"); - - if(Registry->ValueExists("MailMaxClients")) - mail_startup.max_clients=Registry->ReadInteger("MailMaxClients"); - - if(Registry->ValueExists("MailMaxInactivity")) - mail_startup.max_inactivity=Registry->ReadInteger("MailMaxInactivity"); - - if(Registry->ValueExists("MailInterface")) - mail_startup.interface_addr=Registry->ReadInteger("MailInterface"); - - if(Registry->ValueExists("MailMaxDeliveryAttempts")) - mail_startup.max_delivery_attempts - =Registry->ReadInteger("MailMaxDeliveryAttempts"); - - if(Registry->ValueExists("MailRescanFrequency")) - mail_startup.rescan_frequency - =Registry->ReadInteger("MailRescanFrequency"); - - if(Registry->ValueExists("MailSMTPPort")) - mail_startup.smtp_port=Registry->ReadInteger("MailSMTPPort"); - - if(Registry->ValueExists("MailPOP3Port")) - mail_startup.pop3_port=Registry->ReadInteger("MailPOP3Port"); - - if(Registry->ValueExists("MailRelayServer")) - sprintf(mail_startup.relay_server,"%.*s" - ,sizeof(mail_startup.relay_server)-1 - ,Registry->ReadString("MailRelayServer").c_str()); - - if(Registry->ValueExists("MailDNSServer")) - sprintf(mail_startup.dns_server,"%.*s" - ,sizeof(mail_startup.dns_server)-1 - ,Registry->ReadString("MailDNSServer").c_str()); - - if(Registry->ValueExists("MailInboundSound")) - sprintf(mail_startup.inbound_sound,"%.*s" - ,sizeof(mail_startup.inbound_sound)-1 - ,Registry->ReadString("MailInboundSound").c_str()); - - if(Registry->ValueExists("MailOutboundSound")) - sprintf(mail_startup.outbound_sound,"%.*s" - ,sizeof(mail_startup.outbound_sound)-1 - ,Registry->ReadString("MailOutboundSound").c_str()); - - if(Registry->ValueExists("MailPOP3Sound")) - sprintf(mail_startup.pop3_sound,"%.*s" - ,sizeof(mail_startup.pop3_sound)-1 - ,Registry->ReadString("MailPOP3Sound").c_str()); - - if(Registry->ValueExists("MailOptions")) - mail_startup.options=Registry->ReadInteger("MailOptions"); - - if(Registry->ValueExists("FtpMaxClients")) - ftp_startup.max_clients=Registry->ReadInteger("FtpMaxClients"); - - if(Registry->ValueExists("FtpMaxInactivity")) - ftp_startup.max_inactivity=Registry->ReadInteger("FtpMaxInactivity"); - - if(Registry->ValueExists("FtpInterface")) - ftp_startup.interface_addr=Registry->ReadInteger("FtpInterface"); - - if(Registry->ValueExists("FtpPort")) - ftp_startup.port=Registry->ReadInteger("FtpPort"); - - if(Registry->ValueExists("FtpAnswerSound")) - sprintf(ftp_startup.answer_sound,"%.*s" - ,sizeof(ftp_startup.answer_sound)-1 - ,Registry->ReadString("FtpAnswerSound").c_str()); - - if(Registry->ValueExists("FtpHangupSound")) - sprintf(ftp_startup.hangup_sound,"%.*s" - ,sizeof(ftp_startup.hangup_sound)-1 - ,Registry->ReadString("FtpHangupSound").c_str()); - - if(Registry->ValueExists("FtpIndexFileName")) - sprintf(ftp_startup.index_file_name,"%.*s" - ,sizeof(ftp_startup.index_file_name)-1 - ,Registry->ReadString("FtpIndexFileName").c_str()); + FILE* fp; + if((!Registry->ValueExists("SysAutoStart") + || (Registry->ValueExists("Imported") && Registry->ReadBool("Imported"))) + && ini_file[0]) { + if((fp=fopen(ini_file,"r"))==NULL) { + char err[MAX_PATH*2]; + sprintf(err,"Error %d opening initialization file: %s",errno,ini_file); + Application->MessageBox(err,"ERROR",MB_OK|MB_ICONEXCLAMATION); + Application->Terminate(); + return; + } + sbbs_read_ini(fp + ,&global + ,&SysAutoStart ,&bbs_startup + ,&FtpAutoStart ,&ftp_startup + ,&WebAutoStart ,&web_startup + ,&MailAutoStart ,&mail_startup + ,&ServicesAutoStart ,&services_startup + ); + StatusBar->Panels->Items[4]->Text="Read " + AnsiString(ini_file); + fclose(fp); + + } else { /* Legacy (v3.10-3.11) */ + + if(Registry->ValueExists("SysAutoStart")) + SysAutoStart=Registry->ReadInteger("SysAutoStart"); + else + SysAutoStart=true; + + if(Registry->ValueExists("MailAutoStart")) + MailAutoStart=Registry->ReadInteger("MailAutoStart"); + else + MailAutoStart=true; + + if(Registry->ValueExists("FtpAutoStart")) + FtpAutoStart=Registry->ReadInteger("FtpAutoStart"); + else + FtpAutoStart=true; + + if(Registry->ValueExists("WebAutoStart")) + WebAutoStart=Registry->ReadInteger("WebAutoStart"); + else + WebAutoStart=true; + + if(Registry->ValueExists("ServicesAutoStart")) + ServicesAutoStart=Registry->ReadInteger("ServicesAutoStart"); + else + ServicesAutoStart=true; + + if(Registry->ValueExists("Hostname")) + SAFECOPY(global.host_name,Registry->ReadString("Hostname")); + if(Registry->ValueExists("CtrlDirectory")) + SAFECOPY(global.ctrl_dir,Registry->ReadString("CtrlDirectory")); + if(Registry->ValueExists("TempDirectory")) + SAFECOPY(global.temp_dir,Registry->ReadString("TempDirectory")); + + if(Registry->ValueExists("SemFileCheckFrequency")) + global.sem_chk_freq=Registry->ReadInteger("SemFileCheckFrequency"); + + /* JavaScript Operating Parameters */ + if(Registry->ValueExists("JS_MaxBytes")) + global.js.max_bytes=Registry->ReadInteger("JS_MaxBytes"); + if(global.js.max_bytes==0) + global.js.max_bytes=JAVASCRIPT_MAX_BYTES; + if(Registry->ValueExists("JS_ContextStack")) + global.js.cx_stack=Registry->ReadInteger("JS_ContextStack"); + if(global.js.cx_stack==0) + global.js.cx_stack=JAVASCRIPT_CONTEXT_STACK; + if(Registry->ValueExists("JS_BranchLimit")) + global.js.branch_limit=Registry->ReadInteger("JS_BranchLimit"); + if(Registry->ValueExists("JS_GcInterval")) + global.js.gc_interval=Registry->ReadInteger("JS_GcInterval"); + if(Registry->ValueExists("JS_YieldInterval")) + global.js.yield_interval=Registry->ReadInteger("JS_YieldInterval"); + + if(Registry->ValueExists("TelnetInterface")) + bbs_startup.telnet_interface=Registry->ReadInteger("TelnetInterface"); + if(Registry->ValueExists("RLoginInterface")) + bbs_startup.rlogin_interface=Registry->ReadInteger("RLoginInterface"); + + if(Registry->ValueExists("TelnetPort")) + bbs_startup.telnet_port=Registry->ReadInteger("TelnetPort"); + if(Registry->ValueExists("RLoginPort")) + bbs_startup.rlogin_port=Registry->ReadInteger("RLoginPort"); + + if(Registry->ValueExists("FirstNode")) + bbs_startup.first_node=Registry->ReadInteger("FirstNode"); + + if(Registry->ValueExists("LastNode")) + bbs_startup.last_node=Registry->ReadInteger("LastNode"); + + if(Registry->ValueExists("ExternalYield")) + bbs_startup.xtrn_polls_before_yield=Registry->ReadInteger("ExternalYield"); + + if(Registry->ValueExists("OutbufHighwaterMark")) + bbs_startup.outbuf_highwater_mark=Registry->ReadInteger("OutbufHighwaterMark"); + else + bbs_startup.outbuf_highwater_mark=1024; + if(Registry->ValueExists("OutbufDrainTimeout")) + bbs_startup.outbuf_drain_timeout=Registry->ReadInteger("OutbufDrainTimeout"); + else + bbs_startup.outbuf_drain_timeout=10; + + if(Registry->ValueExists("AnswerSound")) + SAFECOPY(bbs_startup.answer_sound + ,Registry->ReadString("AnswerSound").c_str()); + + if(Registry->ValueExists("HangupSound")) + SAFECOPY(bbs_startup.hangup_sound + ,Registry->ReadString("HangupSound").c_str()); + + if(Registry->ValueExists("StartupOptions")) + bbs_startup.options=Registry->ReadInteger("StartupOptions"); + + if(Registry->ValueExists("MailMaxClients")) + mail_startup.max_clients=Registry->ReadInteger("MailMaxClients"); + + if(Registry->ValueExists("MailMaxInactivity")) + mail_startup.max_inactivity=Registry->ReadInteger("MailMaxInactivity"); + + if(Registry->ValueExists("MailInterface")) + mail_startup.interface_addr=Registry->ReadInteger("MailInterface"); + + if(Registry->ValueExists("MailMaxDeliveryAttempts")) + mail_startup.max_delivery_attempts + =Registry->ReadInteger("MailMaxDeliveryAttempts"); + + if(Registry->ValueExists("MailRescanFrequency")) + mail_startup.rescan_frequency + =Registry->ReadInteger("MailRescanFrequency"); + + if(Registry->ValueExists("MailLinesPerYield")) + mail_startup.lines_per_yield + =Registry->ReadInteger("MailLinesPerYield"); + + if(Registry->ValueExists("MailMaxRecipients")) + mail_startup.max_recipients + =Registry->ReadInteger("MailMaxRecipients"); + + if(Registry->ValueExists("MailMaxMsgSize")) + mail_startup.max_msg_size + =Registry->ReadInteger("MailMaxMsgSize"); + + if(Registry->ValueExists("MailSMTPPort")) + mail_startup.smtp_port=Registry->ReadInteger("MailSMTPPort"); + + if(Registry->ValueExists("MailPOP3Port")) + mail_startup.pop3_port=Registry->ReadInteger("MailPOP3Port"); + + if(Registry->ValueExists("MailRelayServer")) + SAFECOPY(mail_startup.relay_server + ,Registry->ReadString("MailRelayServer").c_str()); + + if(Registry->ValueExists("MailRelayPort")) + mail_startup.relay_port=Registry->ReadInteger("MailRelayPort"); + + if(Registry->ValueExists("MailDefaultUser")) + SAFECOPY(mail_startup.default_user + ,Registry->ReadString("MailDefaultUser").c_str()); + + if(Registry->ValueExists("MailDNSBlacklistSubject")) + SAFECOPY(mail_startup.dnsbl_tag + ,Registry->ReadString("MailDNSBlacklistSubject").c_str()); + else + SAFECOPY(mail_startup.dnsbl_tag,"SPAM"); + + if(Registry->ValueExists("MailDNSBlacklistHeader")) + SAFECOPY(mail_startup.dnsbl_hdr + ,Registry->ReadString("MailDNSBlacklistHeader").c_str()); + else + SAFECOPY(mail_startup.dnsbl_hdr,"X-DNSBL"); + + if(Registry->ValueExists("MailDNSServer")) + SAFECOPY(mail_startup.dns_server + ,Registry->ReadString("MailDNSServer").c_str()); + + if(Registry->ValueExists("MailInboundSound")) + SAFECOPY(mail_startup.inbound_sound + ,Registry->ReadString("MailInboundSound").c_str()); + + if(Registry->ValueExists("MailOutboundSound")) + SAFECOPY(mail_startup.outbound_sound + ,Registry->ReadString("MailOutboundSound").c_str()); + + if(Registry->ValueExists("MailPOP3Sound")) + SAFECOPY(mail_startup.pop3_sound + ,Registry->ReadString("MailPOP3Sound").c_str()); + + if(Registry->ValueExists("MailOptions")) + mail_startup.options=Registry->ReadInteger("MailOptions"); + + if(Registry->ValueExists("FtpMaxClients")) + ftp_startup.max_clients=Registry->ReadInteger("FtpMaxClients"); + + if(Registry->ValueExists("FtpMaxInactivity")) + ftp_startup.max_inactivity=Registry->ReadInteger("FtpMaxInactivity"); + + if(Registry->ValueExists("FtpQwkTimeout")) + ftp_startup.qwk_timeout=Registry->ReadInteger("FtpQwkTimeout"); + + if(Registry->ValueExists("FtpInterface")) + ftp_startup.interface_addr=Registry->ReadInteger("FtpInterface"); + + if(Registry->ValueExists("FtpPort")) + ftp_startup.port=Registry->ReadInteger("FtpPort"); + + if(Registry->ValueExists("FtpAnswerSound")) + SAFECOPY(ftp_startup.answer_sound + ,Registry->ReadString("FtpAnswerSound").c_str()); + + if(Registry->ValueExists("FtpHangupSound")) + SAFECOPY(ftp_startup.hangup_sound + ,Registry->ReadString("FtpHangupSound").c_str()); + + if(Registry->ValueExists("FtpHackAttemptSound")) + SAFECOPY(ftp_startup.hack_sound + ,Registry->ReadString("FtpHackAttemptSound").c_str()); + + if(Registry->ValueExists("FtpIndexFileName")) + SAFECOPY(ftp_startup.index_file_name + ,Registry->ReadString("FtpIndexFileName").c_str()); + + if(Registry->ValueExists("FtpHtmlIndexFile")) + SAFECOPY(ftp_startup.html_index_file + ,Registry->ReadString("FtpHtmlIndexFile").c_str()); + + if(Registry->ValueExists("FtpHtmlIndexScript")) + SAFECOPY(ftp_startup.html_index_script + ,Registry->ReadString("FtpHtmlIndexScript").c_str()); + + if(Registry->ValueExists("FtpOptions")) + ftp_startup.options=Registry->ReadInteger("FtpOptions"); + + if(Registry->ValueExists("ServicesInterface")) + services_startup.interface_addr + =Registry->ReadInteger("ServicesInterface"); + + if(Registry->ValueExists("ServicesAnswerSound")) + SAFECOPY(services_startup.answer_sound + ,Registry->ReadString("ServicesAnswerSound").c_str()); + + if(Registry->ValueExists("ServicesHangupSound")) + SAFECOPY(services_startup.hangup_sound + ,Registry->ReadString("ServicesHangupSound").c_str()); - if(Registry->ValueExists("FtpOptions")) - ftp_startup.options=Registry->ReadInteger("FtpOptions"); + if(Registry->ValueExists("ServicesOptions")) + services_startup.options=Registry->ReadInteger("ServicesOptions"); + + if(SaveIniSettings(Sender)) + Registry->WriteBool("Imported",true); /* Use the .ini file for these settings from now on */ + } Registry->CloseKey(); delete Registry; + AnsiString CtrlDirectory = AnsiString(global.ctrl_dir); if(!FileExists(CtrlDirectory+"MAIN.CNF")) { - Sleep(3000); // Let 'em see the logo for a bit Application->CreateForm(__classid(TCtrlPathDialog), &CtrlPathDialog); if(CtrlPathDialog->ShowModal()!=mrOk) { Application->Terminate(); @@ -1400,14 +2097,38 @@ void __fastcall TMainForm::StartupTimerT } if(CtrlDirectory.UpperCase().AnsiPos("MAIN.CNF")) CtrlDirectory.SetLength(CtrlDirectory.Length()-8); - strcpy(cfg.ctrl_dir,CtrlDirectory.c_str()); - if(!load_cfg(&cfg, NULL)) { - Application->MessageBox("Failed to load configuration files.","ERROR" + SAFECOPY(global.ctrl_dir,CtrlDirectory.c_str()); + memset(&cfg,0,sizeof(cfg)); + SAFECOPY(cfg.ctrl_dir,global.ctrl_dir); + cfg.size=sizeof(cfg); + cfg.node_num=bbs_startup.first_node; + char error[256]; + SAFECOPY(error,UNKNOWN_LOAD_ERROR); + if(!load_cfg(&cfg, NULL, TRUE, error)) { + Application->MessageBox(error,"ERROR Loading Configuration" ,MB_OK|MB_ICONEXCLAMATION); Application->Terminate(); return; } + if(!(cfg.sys_misc&SM_LOCAL_TZ)) { + if(putenv("TZ=UTC0")) { + Application->MessageBox("Error setting timezone" + ,"ERROR",MB_OK|MB_ICONEXCLAMATION); + Application->Terminate(); + } + tzset(); + } + + if(cfg.new_install) { + Application->BringToFront(); + for(int i=0;i<10;i++) { + Application->ProcessMessages(); + Sleep(300); // Let 'em see the logo for a bit + } + BBSConfigWizardMenuItemClick(Sender); + } + if(bbs_startup.options&BBS_OPT_MUTE) SoundToggle->Checked=false; else @@ -1428,15 +2149,34 @@ void __fastcall TMainForm::StartupTimerT MailForm->ManualDock(PageControl(MailFormPage),NULL,alClient); if(!TelnetFormFloating) TelnetForm->ManualDock(PageControl(TelnetFormPage),NULL,alClient); + if(!EventsFormFloating) + EventsForm->ManualDock(PageControl(EventsFormPage),NULL,alClient); + if(!ServicesFormFloating) + ServicesForm->ManualDock(PageControl(ServicesFormPage),NULL,alClient); if(!FtpFormFloating) FtpForm->ManualDock(PageControl(FtpFormPage),NULL,alClient); + if(!WebFormFloating) + WebForm->ManualDock(PageControl(WebFormPage),NULL,alClient); NodeForm->Show(); +// ViewNodes->Checked=NodeFormVisible, ViewNodesExecute(Sender); ClientForm->Show(); +// ViewClients->Checked=ClientFormVisible, ViewClientsExecute(Sender); StatsForm->Show(); +// ViewStats->Checked=StatsFormVisible, ViewStatsExecute(Sender); TelnetForm->Show(); +// ViewTelnet->Checked=TelnetFormVisible, ViewTelnetExecute(Sender); + EventsForm->Show(); +// ViewEvents->Checked=EventsFormVisible, ViewEventsExecute(Sender); FtpForm->Show(); +// ViewFtpServer->Checked=FtpFormVisible, ViewFtpServerExecute(Sender); + WebForm->Show(); +// ViewWebServer->Checked=WebFormVisible; +// WebForm->Visible=ViewWebServer->Checked; MailForm->Show(); +// ViewMailServer->Checked=MailFormVisible,ViewMailServerExecute(Sender); + ServicesForm->Show(); +// ViewServices->Checked=ServicesFormVisible,ViewServicesExecute(Sender); UpperLeftPageControl->Visible=true; UpperRightPageControl->Visible=true; @@ -1465,17 +2205,433 @@ void __fastcall TMainForm::StartupTimerT LowerLeftPageControl->ActivePageIndex=i; LowerLeftPageControl->ActivePageIndex=0; - if(SysAutoStart) { - bbs_start(); + LogTimerTick(Sender); /* Open Log Mailslots */ + ServiceStatusTimerTick(Sender); /* Query service config lengths */ + + if(SysAutoStart) + TelnetStartExecute(Sender); + if(MailAutoStart) + MailStartExecute(Sender); + if(FtpAutoStart) + FtpStartExecute(Sender); + if(WebAutoStart) + WebStartExecute(Sender); + if(ServicesAutoStart) + ServicesStartExecute(Sender); + + NodeForm->Timer->Enabled=true; + ClientForm->Timer->Enabled=true; + + StatsTimer->Interval=cfg.node_stat_check*1000; + StatsTimer->Enabled=true; + Initialized=true; + + UpTimer->Enabled=true; /* Start updating the status bar */ + + if(!Application->Active) /* Starting up minimized? */ + FormMinimize(Sender); /* Put icon in systray */ +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::SaveRegistrySettings(TObject* Sender) +{ + StatusBar->Panels->Items[4]->Text="Saving Registry Settings..."; + + // Write Registry keys + TRegistry* Registry=new TRegistry; + if(!Registry->OpenKey(REG_KEY,true)) { + Application->MessageBox("Error creating registry key" + ,REG_KEY,MB_OK|MB_ICONEXCLAMATION); + Application->Terminate(); + return; } - if(MailAutoStart) { - mail_start(); + Registry->WriteInteger("MainFormTop",Top); + Registry->WriteInteger("MainFormLeft",Left); + Registry->WriteInteger("MainFormHeight",Height); + Registry->WriteInteger("MainFormWidth",Width); + + Registry->WriteInteger("NodeFormTop",NodeForm->Top); + Registry->WriteInteger("NodeFormLeft",NodeForm->Left); + Registry->WriteInteger("NodeFormHeight",NodeForm->Height); + Registry->WriteInteger("NodeFormWidth",NodeForm->Width); + + Registry->WriteInteger("StatsFormTop",StatsForm->Top); + Registry->WriteInteger("StatsFormLeft",StatsForm->Left); + Registry->WriteInteger("StatsFormHeight",StatsForm->Height); + Registry->WriteInteger("StatsFormWidth",StatsForm->Width); + + Registry->WriteInteger("ClientFormTop",ClientForm->Top); + Registry->WriteInteger("ClientFormLeft",ClientForm->Left); + Registry->WriteInteger("ClientFormHeight",ClientForm->Height); + Registry->WriteInteger("ClientFormWidth",ClientForm->Width); + + for(int i=0;iListView->Columns->Count;i++) { + char str[128]; + sprintf(str,"ClientListColumn%dWidth",i); + Registry->WriteInteger(str + ,ClientForm->ListView->Columns->Items[i]->Width); } - if(FtpAutoStart) { - ftp_start(); + + Registry->WriteInteger("TelnetFormTop",TelnetForm->Top); + Registry->WriteInteger("TelnetFormLeft",TelnetForm->Left); + Registry->WriteInteger("TelnetFormHeight",TelnetForm->Height); + Registry->WriteInteger("TelnetFormWidth",TelnetForm->Width); + + Registry->WriteInteger("EventsFormTop",EventsForm->Top); + Registry->WriteInteger("EventsFormLeft",EventsForm->Left); + Registry->WriteInteger("EventsFormHeight",EventsForm->Height); + Registry->WriteInteger("EventsFormWidth",EventsForm->Width); + + Registry->WriteInteger("ServicesFormTop",ServicesForm->Top); + Registry->WriteInteger("ServicesFormLeft",ServicesForm->Left); + Registry->WriteInteger("ServicesFormHeight",ServicesForm->Height); + Registry->WriteInteger("ServicesFormWidth",ServicesForm->Width); + + Registry->WriteInteger("FtpFormTop",FtpForm->Top); + Registry->WriteInteger("FtpFormLeft",FtpForm->Left); + Registry->WriteInteger("FtpFormHeight",FtpForm->Height); + Registry->WriteInteger("FtpFormWidth",FtpForm->Width); + + Registry->WriteInteger("WebFormTop",WebForm->Top); + Registry->WriteInteger("WebFormLeft",WebForm->Left); + Registry->WriteInteger("WebFormHeight",WebForm->Height); + Registry->WriteInteger("WebFormWidth",WebForm->Width); + + Registry->WriteInteger("MailFormTop",MailForm->Top); + Registry->WriteInteger("MailFormLeft",MailForm->Left); + Registry->WriteInteger("MailFormHeight",MailForm->Height); + Registry->WriteInteger("MailFormWidth",MailForm->Width); + + Registry->WriteInteger("TopPanelHeight",TopPanel->Height); + Registry->WriteInteger("UpperLeftPageControlWidth" + ,UpperLeftPageControl->Width); + Registry->WriteInteger("LowerLeftPageControlWidth" + ,LowerLeftPageControl->Width); + + Registry->WriteBool("UndockableForms",UndockableForms); + + Registry->WriteBool("TelnetFormFloating",TelnetForm->Floating); + Registry->WriteBool("EventsFormFloating",EventsForm->Floating); + Registry->WriteBool("ServicesFormFloating",ServicesForm->Floating); + Registry->WriteBool("NodeFormFloating",NodeForm->Floating); + Registry->WriteBool("StatsFormFloating",StatsForm->Floating); + Registry->WriteBool("ClientFormFloating",ClientForm->Floating); + Registry->WriteBool("FtpFormFloating",FtpForm->Floating); + Registry->WriteBool("WebFormFloating",WebForm->Floating); + Registry->WriteBool("MailFormFloating",MailForm->Floating); + + Registry->WriteBool("TelnetFormVisible",TelnetForm->Visible); + Registry->WriteBool("EventsFormVisible",EventsForm->Visible); + Registry->WriteBool("ServicesFormVisible",ServicesForm->Visible); + Registry->WriteBool("NodeFormVisible",NodeForm->Visible); + Registry->WriteBool("StatsFormVisible",StatsForm->Visible); + Registry->WriteBool("ClientFormVisible",ClientForm->Visible); + Registry->WriteBool("FtpFormVisible",FtpForm->Visible); + Registry->WriteBool("WebFormVisible",WebForm->Visible); + Registry->WriteBool("MailFormVisible",MailForm->Visible); + + Registry->WriteInteger("TelnetFormPage" + ,PageNum((TPageControl*)TelnetForm->HostDockSite)); + Registry->WriteInteger("EventsFormPage" + ,PageNum((TPageControl*)EventsForm->HostDockSite)); + Registry->WriteInteger("ServicesFormPage" + ,PageNum((TPageControl*)ServicesForm->HostDockSite)); + Registry->WriteInteger("NodeFormPage" + ,PageNum((TPageControl*)NodeForm->HostDockSite)); + Registry->WriteInteger("MailFormPage" + ,PageNum((TPageControl*)MailForm->HostDockSite)); + Registry->WriteInteger("FtpFormPage" + ,PageNum((TPageControl*)FtpForm->HostDockSite)); + Registry->WriteInteger("WebFormPage" + ,PageNum((TPageControl*)WebForm->HostDockSite)); + Registry->WriteInteger("StatsFormPage" + ,PageNum((TPageControl*)StatsForm->HostDockSite)); + Registry->WriteInteger("ClientFormPage" + ,PageNum((TPageControl*)ClientForm->HostDockSite)); + + WriteColor(Registry,"TelnetLog",TelnetForm->Log->Color); + WriteFont("TelnetLog",TelnetForm->Log->Font); + WriteColor(Registry,"EventsLog",EventsForm->Log->Color); + WriteFont("EventsLog",EventsForm->Log->Font); + WriteColor(Registry,"ServicesLog",ServicesForm->Log->Color); + WriteFont("ServicesLog",ServicesForm->Log->Font); + WriteColor(Registry,"MailLog",MailForm->Log->Color); + WriteFont("MailLog",MailForm->Log->Font); + WriteColor(Registry,"FtpLog",FtpForm->Log->Color); + WriteFont("FtpLog",FtpForm->Log->Font); + WriteColor(Registry,"WebLog",WebForm->Log->Color); + WriteFont("WebLog",WebForm->Log->Font); + WriteColor(Registry,"NodeList",NodeForm->ListBox->Color); + WriteFont("NodeList",NodeForm->ListBox->Font); + WriteColor(Registry,"ClientList",ClientForm->ListView->Color); + WriteFont("ClientList",ClientForm->ListView->Font); + + Registry->WriteBool("ToolBarVisible",Toolbar->Visible); + Registry->WriteBool("StatusBarVisible",StatusBar->Visible); + + Registry->WriteInteger("MaxLogLen",MaxLogLen); + + Registry->WriteString("LoginCommand",LoginCommand); + Registry->WriteString("ConfigCommand",ConfigCommand); + Registry->WriteString("Password",Password); + Registry->WriteBool("MinimizeToSysTray",MinimizeToSysTray); + Registry->WriteBool("UseFileAssociations",UseFileAssociations); + Registry->WriteInteger("NodeDisplayInterval",NodeForm->Timer->Interval/1000); + Registry->WriteInteger("ClientDisplayInterval",ClientForm->Timer->Interval/1000); + + Registry->WriteInteger( "SpyTerminalWidth" + ,SpyTerminalWidth); + Registry->WriteInteger( "SpyTerminalHeight" + ,SpyTerminalHeight); + Registry->WriteString( "SpyTerminalFontName" + ,SpyTerminalFont->Name); + Registry->WriteInteger( "SpyTerminalFontSize" + ,SpyTerminalFont->Size); + Registry->WriteBool( "SpyTerminalKeyboardActive" + ,SpyTerminalKeyboardActive); + + Registry->CloseKey(); + delete Registry; +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::SaveSettings(TObject* Sender) +{ + SaveIniSettings(Sender); + SaveRegistrySettings(Sender); +} +//--------------------------------------------------------------------------- +bool __fastcall TMainForm::SaveIniSettings(TObject* Sender) +{ + FILE* fp=NULL; + if(ini_file[0]==0) + return(false); + + if((fp=fopen(ini_file,"r+"))==NULL) { + char err[MAX_PATH*2]; + SAFEPRINTF2(err,"Error %d opening initialization file: %s",errno,ini_file); + Application->MessageBox(err,"ERROR",MB_OK|MB_ICONEXCLAMATION); + return(false); } - NodeForm->Timer->Enabled=true; - StatsTimer->Enabled=true; + + StatusBar->Panels->Items[4]->Text="Saving Settings to " + AnsiString(ini_file) + " ..."; + + bool success = sbbs_write_ini(fp + ,&cfg + ,&global + ,SysAutoStart ,&bbs_startup + ,FtpAutoStart ,&ftp_startup + ,WebAutoStart ,&web_startup + ,MailAutoStart ,&mail_startup + ,ServicesAutoStart ,&services_startup + ); + fclose(fp); + + return(success); +} + +//--------------------------------------------------------------------------- +void __fastcall TMainForm::ImportFormSettings(TMemIniFile* IniFile, const char* section, TForm* Form) +{ + Form->Top=IniFile->ReadInteger(section,"Top",Form->Top); + Form->Left=IniFile->ReadInteger(section,"Left",Form->Left); + Form->Width=IniFile->ReadInteger(section,"Width",Form->Width); + Form->Height=IniFile->ReadInteger(section,"Height",Form->Height); +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::ExportFormSettings(TMemIniFile* IniFile, const char* section, TForm* Form) +{ + IniFile->WriteInteger(section,"Top",Form->Top); + IniFile->WriteInteger(section,"Left",Form->Left); + IniFile->WriteInteger(section,"Width",Form->Width); + IniFile->WriteInteger(section,"Height",Form->Height); + IniFile->WriteInteger(section,"Page",PageNum((TPageControl*)Form->HostDockSite)); + IniFile->WriteBool(section,"Floating",Form->Floating); +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::ImportFont(TMemIniFile* IniFile, const char* section, AnsiString prefix, TFont* Font) +{ + Font->Name=IniFile->ReadString(section,prefix + "Name",Font->Name); + Font->Color=StringToColor(IniFile->ReadString(section,prefix + "Color",ColorToString(Font->Color))); + Font->Height=IniFile->ReadInteger(section,prefix + "Height",Font->Height); + Font->Size=IniFile->ReadInteger(section,prefix + "Size", Font->Size); + IntToFontStyle(IniFile->ReadInteger(section,prefix + "Style",FontStyleToInt(Font)),Font); +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::ExportFont(TMemIniFile* IniFile, const char* section, AnsiString prefix, TFont* Font) +{ + IniFile->WriteString(section,prefix+"Name",Font->Name); + IniFile->WriteString(section,prefix+"Color",ColorToString(Font->Color)); + IniFile->WriteInteger(section,prefix+"Height",Font->Height); + IniFile->WriteInteger(section,prefix+"Size",Font->Size); + IniFile->WriteInteger(section,prefix+"Style",FontStyleToInt(Font)); +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::ImportSettings(TObject* Sender) +{ + OpenDialog->Filter="Settings files (*.ini)|*.ini|All files|*.*"; + OpenDialog->FileName=AnsiString(global.ctrl_dir)+"sbbsctrl.ini"; + if(!OpenDialog->Execute()) + return; + + StatusBar->Panels->Items[4]->Text="Importing Settings..."; + + TMemIniFile* IniFile=new TMemIniFile(OpenDialog->FileName); + + const char* section = "Properties"; + + LoginCommand=IniFile->ReadString(section,"LoginCommand",LoginCommand); + ConfigCommand=IniFile->ReadString(section,"ConfigCommand",ConfigCommand); + Password=IniFile->ReadString(section,"Password",Password); + MinimizeToSysTray=IniFile->ReadBool(section,"MinimizeToSysTray",MinimizeToSysTray); + UseFileAssociations=IniFile->ReadBool(section,"UseFileAssociations" ,UseFileAssociations); + UndockableForms=IniFile->ReadBool(section,"UndockableForms",UndockableForms); + + ImportFormSettings(IniFile,section="MainForm",MainForm); + TopPanel->Height=IniFile->ReadInteger(section,"TopPanelHeight",TopPanel->Height); + UpperLeftPageControl->Width=IniFile->ReadInteger(section,"UpperLeftPageControlWidth",UpperLeftPageControl->Width); + LowerLeftPageControl->Width=IniFile->ReadInteger(section,"LowerLeftPageControlWidth",LowerLeftPageControl->Width); + Toolbar->Visible=IniFile->ReadBool(section,"ToolBarVisible",Toolbar->Visible); + StatusBar->Visible=IniFile->ReadBool(section,"StatusBarVisible",StatusBar->Visible); + + ImportFormSettings(IniFile,section="TelnetForm",TelnetForm); + ImportFont(IniFile,section,"LogFont",TelnetForm->Log->Font); + TelnetForm->Log->Color=StringToColor(IniFile->ReadString(section,"LogColor",clWindow)); + + ImportFormSettings(IniFile,section="EventsForm",EventsForm); + ImportFont(IniFile,section,"LogFont",EventsForm->Log->Font); + EventsForm->Log->Color=StringToColor(IniFile->ReadString(section,"LogColor",clWindow)); + + ImportFormSettings(IniFile,section="ServicesForm",ServicesForm); + ImportFont(IniFile,section,"LogFont",ServicesForm->Log->Font); + ServicesForm->Log->Color=StringToColor(IniFile->ReadString(section,"LogColor",clWindow)); + + ImportFormSettings(IniFile,section="FtpForm",FtpForm); + ImportFont(IniFile,section,"LogFont",FtpForm->Log->Font); + FtpLogFile=IniFile->ReadInteger(section,"LogFile",true); + FtpForm->Log->Color=StringToColor(IniFile->ReadString(section,"LogColor",clWindow)); + + ImportFormSettings(IniFile,section="WebForm",WebForm); + ImportFont(IniFile,section,"LogFont",WebForm->Log->Font); + WebForm->Log->Color=StringToColor(IniFile->ReadString(section,"LogColor",clWindow)); + + ImportFormSettings(IniFile,section="MailForm",MailForm); + ImportFont(IniFile,section,"LogFont",MailForm->Log->Font); + MailLogFile=IniFile->ReadInteger(section,"LogFile",true); + MailForm->Log->Color=StringToColor(IniFile->ReadString(section,"LogColor",clWindow)); + + ImportFormSettings(IniFile,section="NodeForm",NodeForm); + ImportFont(IniFile,section,"ListFont",NodeForm->ListBox->Font); + NodeForm->Timer->Interval=IniFile->ReadInteger(section,"DisplayInterval" + ,NodeForm->Timer->Interval/1000)*1000; + NodeForm->ListBox->Color=StringToColor(IniFile->ReadString(section,"ListColor",clWindow)); + + ImportFormSettings(IniFile,section="StatsForm",StatsForm); + + ImportFormSettings(IniFile,section="ClientForm",ClientForm); + ImportFont(IniFile,section,"ListFont",ClientForm->ListView->Font); + ClientForm->ListView->Color=StringToColor(IniFile->ReadString(section,"ListColor",clWindow)); + ClientForm->Timer->Interval=IniFile->ReadInteger(section,"DisplayInterval" + ,ClientForm->Timer->Interval/1000)*1000; + for(int i=0;iListView->Columns->Count;i++) { + char str[128]; + sprintf(str,"Column%dWidth",i); + if(IniFile->ValueExists(section,str)) + ClientForm->ListView->Columns->Items[i]->Width + =IniFile->ReadInteger(section,str,0); + } + + section = "SpyTerminal"; + SpyTerminalWidth=IniFile->ReadInteger(section, "Width", SpyTerminalWidth); + SpyTerminalHeight=IniFile->ReadInteger(section, "Height", SpyTerminalHeight); + SpyTerminalFont->Name=IniFile->ReadString(section, "FontName", SpyTerminalFont->Name); + SpyTerminalFont->Size=IniFile->ReadInteger(section, "FontSize", SpyTerminalFont->Size); + SpyTerminalKeyboardActive=IniFile->ReadBool(section, "KeyboardActive", SpyTerminalKeyboardActive); + + delete IniFile; + + Application->MessageBox(AnsiString("Successfully imported SBBSCTRL settings from " + + OpenDialog->FileName).c_str(),"Successful Import",MB_OK); +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::ExportSettings(TObject* Sender) +{ + char str[128]; + + SaveDialog->Filter="Settings files (*.ini)|*.ini|All files|*.*"; + SaveDialog->FileName=AnsiString(global.ctrl_dir)+"sbbsctrl.ini"; + if(!SaveDialog->Execute()) + return; + + TMemIniFile* IniFile=new TMemIniFile(SaveDialog->FileName); + + StatusBar->Panels->Items[4]->Text="Exporting Settings..."; + + const char* section = "Properties"; + + IniFile->WriteString(section,"LoginCommand",LoginCommand); + IniFile->WriteString(section,"ConfigCommand",ConfigCommand); + IniFile->WriteString(section,"Password",Password); + IniFile->WriteBool(section,"MinimizeToSysTray",MinimizeToSysTray); + IniFile->WriteBool(section,"UseFileAssociations",UseFileAssociations); + IniFile->WriteBool(section,"UndockableForms",UndockableForms); + + ExportFormSettings(IniFile,section="MainForm",MainForm); + IniFile->WriteInteger(section,"TopPanelHeight",TopPanel->Height); + IniFile->WriteInteger(section,"UpperLeftPageControlWidth",UpperLeftPageControl->Width); + IniFile->WriteInteger(section,"LowerLeftPageControlWidth",LowerLeftPageControl->Width); + IniFile->WriteBool(section,"ToolBarVisible",Toolbar->Visible); + IniFile->WriteBool(section,"StatusBarVisible",StatusBar->Visible); + + ExportFormSettings(IniFile,section = "NodeForm",NodeForm); + ExportFont(IniFile,section,"ListFont",NodeForm->ListBox->Font); + IniFile->WriteString(section,"ListColor",ColorToString(NodeForm->ListBox->Color)); + IniFile->WriteInteger(section,"DisplayInterval",NodeForm->Timer->Interval/1000); + + ExportFormSettings(IniFile,section = "StatsForm",StatsForm); + + ExportFormSettings(IniFile,section = "ClientForm",ClientForm); + ExportFont(IniFile,section,"ListFont",ClientForm->ListView->Font); + IniFile->WriteString(section,"ListColor",ColorToString(ClientForm->ListView->Color)); + IniFile->WriteInteger(section,"DisplayInterval",ClientForm->Timer->Interval/1000); + for(int i=0;iListView->Columns->Count;i++) { + char str[128]; + sprintf(str,"Column%dWidth",i); + IniFile->WriteInteger(section,str + ,ClientForm->ListView->Columns->Items[i]->Width); + } + + ExportFormSettings(IniFile,section = "TelnetForm",TelnetForm); + ExportFont(IniFile,section,"LogFont",TelnetForm->Log->Font); + + ExportFormSettings(IniFile,section = "EventsForm",EventsForm); + ExportFont(IniFile,section,"LogFont",EventsForm->Log->Font); + + ExportFormSettings(IniFile,section = "ServicesForm",ServicesForm); + ExportFont(IniFile,section,"LogFont",ServicesForm->Log->Font); + + ExportFormSettings(IniFile,section = "FtpForm",FtpForm); + ExportFont(IniFile,section,"LogFont",FtpForm->Log->Font); + + ExportFormSettings(IniFile,section = "MailForm",MailForm); + ExportFont(IniFile,section,"LogFont",MailForm->Log->Font); + + section = "SpyTerminal"; + IniFile->WriteInteger(section, "Width" + ,SpyTerminalWidth); + IniFile->WriteInteger(section, "Height" + ,SpyTerminalHeight); + IniFile->WriteString(section, "FontName" + ,SpyTerminalFont->Name); + IniFile->WriteInteger(section, "FontSize" + ,SpyTerminalFont->Size); + IniFile->WriteBool(section, "KeyboardActive" + ,SpyTerminalKeyboardActive); + + IniFile->UpdateFile(); + + delete IniFile; + + Application->MessageBox(AnsiString("Successfully exported SBBSCTRL settings to " + + SaveDialog->FileName).c_str(),"Successful Export",MB_OK); } //--------------------------------------------------------------------------- @@ -1485,8 +2641,6 @@ void __fastcall TMainForm::ViewStatusBar ViewStatusBarMenuItem->Checked=StatusBar->Visible; } //--------------------------------------------------------------------------- - - void __fastcall TMainForm::HelpAboutMenuItemClick(TObject *Sender) { Application->CreateForm(__classid(TAboutBoxForm), &AboutBoxForm); @@ -1494,26 +2648,39 @@ void __fastcall TMainForm::HelpAboutMenu delete AboutBoxForm; } //--------------------------------------------------------------------------- +BOOL MuteService(SC_HANDLE svc, SERVICE_STATUS* status, BOOL mute) +{ + if(svc==NULL || controlService==NULL) + return(FALSE); - - + return controlService(svc + ,mute ? SERVICE_CONTROL_MUTE:SERVICE_CONTROL_UNMUTE, status); +} +//--------------------------------------------------------------------------- void __fastcall TMainForm::SoundToggleExecute(TObject *Sender) { SoundToggle->Checked=!SoundToggle->Checked; + if(!SoundToggle->Checked) { bbs_startup.options|=BBS_OPT_MUTE; ftp_startup.options|=FTP_OPT_MUTE; + web_startup.options|=FTP_OPT_MUTE; mail_startup.options|=MAIL_OPT_MUTE; + services_startup.options|=MAIL_OPT_MUTE; } else { bbs_startup.options&=~BBS_OPT_MUTE; ftp_startup.options&=~FTP_OPT_MUTE; + web_startup.options&=~FTP_OPT_MUTE; mail_startup.options&=~MAIL_OPT_MUTE; + services_startup.options&=~MAIL_OPT_MUTE; } + MuteService(bbs_svc,&bbs_svc_status,!SoundToggle->Checked); + MuteService(ftp_svc,&ftp_svc_status,!SoundToggle->Checked); + MuteService(web_svc,&web_svc_status,!SoundToggle->Checked); + MuteService(mail_svc,&mail_svc_status,!SoundToggle->Checked); + MuteService(services_svc,&services_svc_status,!SoundToggle->Checked); } //--------------------------------------------------------------------------- - - - void __fastcall TMainForm::BBSStatisticsLogMenuItemClick(TObject *Sender) { StatsForm->LogButtonClick(Sender); @@ -1527,12 +2694,15 @@ void __fastcall TMainForm::ForceTimedEve Application->CreateForm(__classid(TCodeInputForm), &CodeInputForm); CodeInputForm->Label->Caption="Event Internal Code"; - if(cfg.total_events) - CodeInputForm->Edit->Text=AnsiString(cfg.event[0]->code); + CodeInputForm->ComboBox->Items->Clear(); + for(i=0;iComboBox->Items->Add( + AnsiString(cfg.event[i]->code).UpperCase()); + CodeInputForm->ComboBox->ItemIndex=0; if(CodeInputForm->ShowModal()==mrOk - && CodeInputForm->Edit->Text.Length()) { + && CodeInputForm->ComboBox->Text.Length()) { for(i=0;iEdit->Text.c_str(),cfg.event[i]->code)) { + if(!stricmp(CodeInputForm->ComboBox->Text.c_str(),cfg.event[i]->code)) { sprintf(str,"%s%s.now",cfg.data_dir,cfg.event[i]->code); if((file=_sopen(str,O_CREAT|O_TRUNC|O_WRONLY ,SH_DENYRW,S_IREAD|S_IWRITE))!=-1) @@ -1541,8 +2711,8 @@ void __fastcall TMainForm::ForceTimedEve } } if(i>=cfg.total_events) - Application->MessageBox("Event Code Not Found" - ,CodeInputForm->Edit->Text.c_str(),MB_OK|MB_ICONEXCLAMATION); + Application->MessageBox(CodeInputForm->ComboBox->Text.c_str() + ,"Event Code Not Found",MB_OK|MB_ICONEXCLAMATION); } delete CodeInputForm; } @@ -1556,12 +2726,15 @@ void __fastcall TMainForm::ForceNetworkC Application->CreateForm(__classid(TCodeInputForm), &CodeInputForm); CodeInputForm->Label->Caption="Hub QWK-ID"; - if(cfg.total_qhubs) - CodeInputForm->Edit->Text=AnsiString(cfg.qhub[0]->id); + CodeInputForm->ComboBox->Items->Clear(); + for(i=0;iComboBox->Items->Add( + AnsiString(cfg.qhub[i]->id).UpperCase()); + CodeInputForm->ComboBox->ItemIndex=0; if(CodeInputForm->ShowModal()==mrOk - && CodeInputForm->Edit->Text.Length()) { + && CodeInputForm->ComboBox->Text.Length()) { for(i=0;iEdit->Text.c_str(),cfg.qhub[i]->id)) { + if(!stricmp(CodeInputForm->ComboBox->Text.c_str(),cfg.qhub[i]->id)) { sprintf(str,"%sqnet/%s.now",cfg.data_dir,cfg.qhub[i]->id); if((file=_sopen(str,O_CREAT|O_TRUNC|O_WRONLY ,SH_DENYRW,S_IREAD|S_IWRITE))!=-1) @@ -1570,8 +2743,8 @@ void __fastcall TMainForm::ForceNetworkC } } if(i>=cfg.total_qhubs) - Application->MessageBox("QWKnet Hub ID Not Found" - ,CodeInputForm->Edit->Text.c_str(),MB_OK|MB_ICONEXCLAMATION); + Application->MessageBox(CodeInputForm->ComboBox->Text.c_str() + ,"QWKnet Hub ID Not Found",MB_OK|MB_ICONEXCLAMATION); } delete CodeInputForm; } @@ -1584,29 +2757,29 @@ void __fastcall TMainForm::TextMenuItemE sprintf(filename,"%s%s" ,MainForm->cfg.text_dir ,((TMenuItem*)Sender)->Hint.c_str()); - Application->CreateForm(__classid(TTextFileEditForm), &TextFileEditForm); - TextFileEditForm->Filename=AnsiString(filename); - TextFileEditForm->Caption=((TMenuItem*)Sender)->Caption; - TextFileEditForm->ShowModal(); - delete TextFileEditForm; - + EditFile(filename,((TMenuItem*)Sender)->Caption); } -//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- void __fastcall TMainForm::CtrlMenuItemEditClick(TObject *Sender) { char filename[MAX_PATH+1]; - sprintf(filename,"%s%s" + iniFileName(filename,sizeof(filename) ,MainForm->cfg.ctrl_dir ,((TMenuItem*)Sender)->Hint.c_str()); - Application->CreateForm(__classid(TTextFileEditForm), &TextFileEditForm); - TextFileEditForm->Filename=AnsiString(filename); - TextFileEditForm->Caption=((TMenuItem*)Sender)->Caption; - TextFileEditForm->ShowModal(); - delete TextFileEditForm; + EditFile(filename,((TMenuItem*)Sender)->Caption); +} +void __fastcall TMainForm::DataMenuItemClick(TObject *Sender) +{ + char filename[MAX_PATH+1]; + sprintf(filename,"%s%s" + ,MainForm->cfg.data_dir + ,((TMenuItem*)Sender)->Hint.c_str()); + EditFile(filename,((TMenuItem*)Sender)->Caption); } +//--------------------------------------------------------------------------- //--------------------------------------------------------------------------- @@ -1634,6 +2807,28 @@ void __fastcall TMainForm::UpTimerTick(T AnsiString Str=AnsiString(str); if(MainForm->StatusBar->Panels->Items[4]->Text!=Str) MainForm->StatusBar->Panels->Items[4]->Text=Str; +#if 0 + THeapStatus hp=GetHeapStatus(); + sprintf(str,"Mem Used: %lu bytes",hp.TotalAllocated); + Str=AnsiString(str); + if(MainForm->StatusBar->Panels->Items[5]->Text!=Str) + MainForm->StatusBar->Panels->Items[5]->Text=Str; +#endif + if(TrayIcon->Visible) { + /* Animate TrayIcon when in use */ + AnsiString NumClients; + try { + if(clients) { + TrayIcon->IconIndex=(TrayIcon->IconIndex==4) ? 59 : 4; + NumClients=" ("+AnsiString(clients)+" client"; + if(clients>1) + NumClients+="s"; + NumClients+=")"; + } else if(TrayIcon->IconIndex!=4) + TrayIcon->IconIndex=4; + TrayIcon->Hint=AnsiString(APP_TITLE)+NumClients; + } catch(...) { /* ignore exceptions here */ }; + } } //--------------------------------------------------------------------------- @@ -1642,13 +2837,8 @@ void __fastcall TMainForm::BBSViewErrorL char filename[MAX_PATH+1]; sprintf(filename,"%sERROR.LOG" - ,MainForm->cfg.data_dir); - Application->CreateForm(__classid(TTextFileEditForm), &TextFileEditForm); - TextFileEditForm->Filename=AnsiString(filename); - TextFileEditForm->Caption="Error Log (See SYSOP.DOC for help)"; - TextFileEditForm->Memo->ReadOnly=true; - TextFileEditForm->ShowModal(); - delete TextFileEditForm; + ,MainForm->cfg.logs_dir); + ViewFile(filename,"Error Log"); } //--------------------------------------------------------------------------- @@ -1660,17 +2850,12 @@ void __fastcall TMainForm::ChatToggleExe else bbs_startup.options&=~BBS_OPT_SYSOP_AVAILABLE; + if(bbs_svc!=NULL && controlService!=NULL) + controlService(bbs_svc + ,ChatToggle->Checked ? SERVICE_CONTROL_SYSOP_AVAILABLE : SERVICE_CONTROL_SYSOP_UNAVAILABLE + ,&bbs_svc_status); } //--------------------------------------------------------------------------- - -void __fastcall TMainForm::ViewClientsExecute(TObject *Sender) -{ - ClientForm->Visible=!ClientForm->Visible; - ViewClients->Checked=ClientForm->Visible; -} -//--------------------------------------------------------------------------- - - void __fastcall TMainForm::UserEditExecute(TObject *Sender) { char str[256]; @@ -1680,40 +2865,35 @@ void __fastcall TMainForm::UserEditExecu } //--------------------------------------------------------------------------- -void __fastcall TMainForm::FileOpenMenuItemClick(TObject *Sender) +void __fastcall TMainForm::BBSPreviewMenuItemClick(TObject *Sender) { TOpenDialog* dlg=new TOpenDialog((TComponent*)Sender); - dlg->Filter = "Text files (*.txt)|*.TXT" - "|Log files (*.log)|*.LOG" - "|Config files (*.cfg)|*.CFG" - "|Message files (*.msg; *.asc)|*.MSG;*.ASC" - "|Baja Source (*.src)|*.SRC" + dlg->Options << ofNoChangeDir; + dlg->Filter = "ANSI/Ctrl-A files (*.asc; *.msg; *.ans)|*.ASC;*.MSG;*.ANS" "|All files|*.*"; dlg->InitialDir=cfg.text_dir; if(dlg->Execute()==true) { - Application->CreateForm(__classid(TTextFileEditForm), &TextFileEditForm); - TextFileEditForm->Filename=AnsiString(dlg->FileName); - TextFileEditForm->Caption="Edit"; - TextFileEditForm->ShowModal(); - delete TextFileEditForm; + Application->CreateForm(__classid(TPreviewForm), &PreviewForm); + PreviewForm->Filename=AnsiString(dlg->FileName); + PreviewForm->ShowModal(); + delete PreviewForm; } delete dlg; } //--------------------------------------------------------------------------- - - void __fastcall TMainForm::BBSLoginMenuItemClick(TObject *Sender) { - if(!strnicmp(LoginCommand.c_str(),"start ",6)) - WinExec(LoginCommand.c_str(),SW_SHOWMINNOACTIVE); + if(!strnicmp(LoginCommand.c_str(),"start ",6)) /* Doesn't work on NT */ + ShellExecute(Handle, "open", LoginCommand.c_str()+6, + NULL,NULL,SW_SHOWDEFAULT); + else if(!strnicmp(LoginCommand.c_str(),"telnet:",7)) + ShellExecute(Handle, "open", LoginCommand.c_str(), + NULL,NULL,SW_SHOWDEFAULT); else WinExec(LoginCommand.c_str(),SW_SHOWNORMAL); - } //--------------------------------------------------------------------------- - - void __fastcall TMainForm::ViewLogClick(TObject *Sender) { char str[128]; @@ -1725,9 +2905,10 @@ void __fastcall TMainForm::ViewLogClick( if(((TMenuItem*)Sender)->Tag==-1) { Application->CreateForm(__classid(TCodeInputForm), &CodeInputForm); CodeInputForm->Label->Caption="Date"; - CodeInputForm->Edit->Text=AnsiString(unixtodstr(&cfg,time(NULL),str)); + CodeInputForm->ComboBox->Items->Clear(); + CodeInputForm->ComboBox->Text=AnsiString(unixtodstr(&cfg,time(NULL),str)); mr=CodeInputForm->ShowModal(); - t=dstrtounix(&cfg,CodeInputForm->Edit->Text.c_str()); + t=dstrtounix(&cfg,CodeInputForm->ComboBox->Text.c_str()); delete CodeInputForm; if(mr!=mrOk) return; @@ -1735,34 +2916,607 @@ void __fastcall TMainForm::ViewLogClick( t=time(NULL); t-=((TMenuItem*)Sender)->Tag*24*60*60; } - tm=gmtime(&t); + tm=localtime(&t); if(tm==NULL) return; /* Close Mail/FTP logs */ - mail_lputs(NULL); - ftp_lputs(NULL); + mail_lputs(NULL,0,NULL); + ftp_lputs(NULL,0,NULL); sprintf(filename,"%sLOGS\\%s%02d%02d%02d.LOG" - ,MainForm->cfg.data_dir + ,MainForm->cfg.logs_dir ,((TMenuItem*)Sender)->Hint.c_str() ,tm->tm_mon+1 ,tm->tm_mday ,tm->tm_year%100 ); - Application->CreateForm(__classid(TTextFileEditForm), &TextFileEditForm); - TextFileEditForm->Filename=AnsiString(filename); - TextFileEditForm->Caption=((TMenuItem*)Sender)->Caption; - TextFileEditForm->Memo->ReadOnly=true; - TextFileEditForm->ShowModal(); - delete TextFileEditForm; + ViewFile(filename,((TMenuItem*)Sender)->Caption); } //--------------------------------------------------------------------------- - - void __fastcall TMainForm::UserListExecute(TObject *Sender) { UserListForm->Show(); } //--------------------------------------------------------------------------- +void __fastcall TMainForm::WebPageMenuItemClick(TObject *Sender) +{ + ShellExecute(Handle, "open", ((TMenuItem*)Sender)->Hint.c_str(), + NULL,NULL,SW_SHOWDEFAULT); +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::FormMinimize(TObject *Sender) +{ + if(MinimizeToSysTray) { + if(Password.Length()) { + TrayIcon->RestoreOn=imNone; + CloseTrayMenuItem->Enabled=false; + ConfigureTrayMenuItem->Enabled=false; + UserEditTrayMenuItem->Enabled=false; + } else { + TrayIcon->RestoreOn=imLeftClickUp; + CloseTrayMenuItem->Enabled=true; + ConfigureTrayMenuItem->Enabled=true; + UserEditTrayMenuItem->Enabled=true; + } + if(!TrayIcon->Visible) + TrayIcon->Visible=true; + TrayIcon->Minimize(); + } +} + +void __fastcall TMainForm::TrayIconRestore(TObject *Sender) +{ + TrayIcon->Visible=false; +} + +//--------------------------------------------------------------------------- + +void __fastcall TMainForm::PropertiesExecute(TObject *Sender) +{ + static inside; + if(inside) return; + inside=true; + + Application->CreateForm(__classid(TPropertiesDlg), &PropertiesDlg); + PropertiesDlg->LoginCmdEdit->Text=LoginCommand; + PropertiesDlg->ConfigCmdEdit->Text=ConfigCommand; + PropertiesDlg->HostnameEdit->Text=global.host_name; + PropertiesDlg->CtrlDirEdit->Text=global.ctrl_dir; + PropertiesDlg->TempDirEdit->Text=global.temp_dir; + PropertiesDlg->NodeIntUpDown->Position=NodeForm->Timer->Interval/1000; + PropertiesDlg->ClientIntUpDown->Position=ClientForm->Timer->Interval/1000; + PropertiesDlg->SemFreqUpDown->Position=global.sem_chk_freq; + PropertiesDlg->TrayIconCheckBox->Checked=MinimizeToSysTray; + PropertiesDlg->UndockableCheckBox->Checked=UndockableForms; + PropertiesDlg->FileAssociationsCheckBox->Checked=UseFileAssociations; + PropertiesDlg->PasswordEdit->Text=Password; + PropertiesDlg->JS_MaxBytesEdit->Text=IntToStr(global.js.max_bytes); + PropertiesDlg->JS_ContextStackEdit->Text=IntToStr(global.js.cx_stack); + PropertiesDlg->JS_BranchLimitEdit->Text=IntToStr(global.js.branch_limit); + PropertiesDlg->JS_GcIntervalEdit->Text=IntToStr(global.js.gc_interval); + PropertiesDlg->JS_YieldIntervalEdit->Text=IntToStr(global.js.yield_interval); + + if(MaxLogLen==0) + PropertiesDlg->MaxLogLenEdit->Text=""; + else + PropertiesDlg->MaxLogLenEdit->Text=IntToStr(MaxLogLen); + if(PropertiesDlg->ShowModal()==mrOk) { + LoginCommand=PropertiesDlg->LoginCmdEdit->Text; + ConfigCommand=PropertiesDlg->ConfigCmdEdit->Text; + SAFECOPY(global.host_name,PropertiesDlg->HostnameEdit->Text.c_str()); + SAFECOPY(global.ctrl_dir,PropertiesDlg->CtrlDirEdit->Text.c_str()); + SAFECOPY(global.temp_dir,PropertiesDlg->TempDirEdit->Text.c_str()); + Password=PropertiesDlg->PasswordEdit->Text; + NodeForm->Timer->Interval=PropertiesDlg->NodeIntUpDown->Position*1000; + ClientForm->Timer->Interval=PropertiesDlg->ClientIntUpDown->Position*1000; + global.sem_chk_freq=PropertiesDlg->SemFreqUpDown->Position; + MinimizeToSysTray=PropertiesDlg->TrayIconCheckBox->Checked; + UndockableForms=PropertiesDlg->UndockableCheckBox->Checked; + UseFileAssociations=PropertiesDlg->FileAssociationsCheckBox->Checked; + global.js.max_bytes + =PropertiesDlg->JS_MaxBytesEdit->Text.ToIntDef(JAVASCRIPT_MAX_BYTES); + global.js.cx_stack + =PropertiesDlg->JS_ContextStackEdit->Text.ToIntDef(JAVASCRIPT_CONTEXT_STACK); + global.js.branch_limit + =PropertiesDlg->JS_BranchLimitEdit->Text.ToIntDef(JAVASCRIPT_BRANCH_LIMIT); + global.js.gc_interval + =PropertiesDlg->JS_GcIntervalEdit->Text.ToIntDef(JAVASCRIPT_GC_INTERVAL); + global.js.yield_interval + =PropertiesDlg->JS_YieldIntervalEdit->Text.ToIntDef(JAVASCRIPT_YIELD_INTERVAL); + + MaxLogLen + =PropertiesDlg->MaxLogLenEdit->Text.ToIntDef(0); + SaveSettings(Sender); + } + delete PropertiesDlg; + + inside=false; +} +//--------------------------------------------------------------------------- + +void __fastcall TMainForm::CloseTrayMenuItemClick(TObject *Sender) +{ + Close(); +} +//--------------------------------------------------------------------------- + +void __fastcall TMainForm::RestoreTrayMenuItemClick(TObject *Sender) +{ +#if 0 + TrayIcon->Visible=false; + Application->Restore(); +#else + static inside; + if(inside) + return; + inside=true; + + if(Password.Length()) { + Application->CreateForm(__classid(TCodeInputForm), &CodeInputForm); + CodeInputForm->Label->Caption="Password"; + CodeInputForm->Edit->Visible=true; + CodeInputForm->Edit->PasswordChar='*'; + if(CodeInputForm->ShowModal()==mrOk + && CodeInputForm->Edit->Text.AnsiCompareIC(Password)==0) + TrayIcon->Restore(); + delete CodeInputForm; + } else + TrayIcon->Restore(); + + inside=false; +#endif +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::BBSConfigWizardMenuItemClick(TObject *Sender) +{ + TConfigWizard* ConfigWizard; + static inside; + if(inside) return; + inside=true; + + Application->CreateForm(__classid(TConfigWizard), &ConfigWizard); + if(ConfigWizard->ShowModal()==mrOk) { + SaveSettings(Sender); + ReloadConfigExecute(Sender); + } + delete ConfigWizard; + + inside=false; +} +//--------------------------------------------------------------------------- + +void __fastcall TMainForm::PageControlUnDock(TObject *Sender, + TControl *Client, TWinControl *NewTarget, bool &Allow) +{ + if(NewTarget==NULL) /* Desktop */ + Allow=UndockableForms; +} +//--------------------------------------------------------------------------- + +void __fastcall TMainForm::ReloadConfigExecute(TObject *Sender) +{ + FtpRecycleExecute(Sender); + WebRecycleExecute(Sender); + MailRecycleExecute(Sender); + ServicesRecycleExecute(Sender); + + char error[256]; + SAFECOPY(error,UNKNOWN_LOAD_ERROR); + if(!load_cfg(&cfg, NULL, TRUE, error)) { + Application->MessageBox(error,"ERROR Re-loading Configuration" + ,MB_OK|MB_ICONEXCLAMATION); + Application->Terminate(); + } + + node_t node; + for(int i=0;igetnodedat(i+1,&node,&file)) + break; + node.misc|=NODE_RRUN; + if(NodeForm->putnodedat(i+1,&node,file)) + break; + } +} + +//--------------------------------------------------------------------------- + + +void __fastcall TMainForm::ServicesConfigureExecute(TObject *Sender) +{ + static inside; + if(inside) return; + inside=true; + + Application->CreateForm(__classid(TServicesCfgDlg), &ServicesCfgDlg); + ServicesCfgDlg->ShowModal(); + delete ServicesCfgDlg; + + inside=false; +} +//--------------------------------------------------------------------------- + +void __fastcall TMainForm::UserTruncateMenuItemClick(TObject *Sender) +{ + int usernumber; + int deleted=0; + user_t user; + + Screen->Cursor=crHourGlass; + while((user.number=lastuser(&cfg))!=0) { + if(getuserdat(&cfg,&user)!=0) + break; + if(!(user.misc&DELETED)) + break; + if(!del_lastuser(&cfg)) + break; + deleted++; + } + Screen->Cursor=crDefault; + char str[128]; + sprintf(str,"%u Deleted User Records Removed",deleted); + Application->MessageBox(str,"Users Truncated",MB_OK); +} + +BOOL RecycleService(SC_HANDLE svc, SERVICE_STATUS* status) +{ + if(svc==NULL || controlService==NULL) + return(FALSE); + + return controlService(svc, SERVICE_CONTROL_RECYCLE, status); +} + +//--------------------------------------------------------------------------- +void __fastcall TMainForm::MailRecycleExecute(TObject *Sender) +{ + if(!RecycleService(mail_svc,&mail_svc_status)) { + mail_startup.recycle_now=true; + MailRecycle->Enabled=false; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::FtpRecycleExecute(TObject *Sender) +{ + if(!RecycleService(ftp_svc,&ftp_svc_status)) { + ftp_startup.recycle_now=true; + FtpRecycle->Enabled=false; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::WebRecycleExecute(TObject *Sender) +{ + if(!RecycleService(web_svc,&web_svc_status)) { + web_startup.recycle_now=true; + WebRecycle->Enabled=false; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::ServicesRecycleExecute(TObject *Sender) +{ + if(!RecycleService(services_svc,&services_svc_status)) { + services_startup.recycle_now=true; + ServicesRecycle->Enabled=false; + } +} +//--------------------------------------------------------------------------- + +void __fastcall TMainForm::TelnetRecycleExecute(TObject *Sender) +{ + if(!RecycleService(bbs_svc,&bbs_svc_status)) { + bbs_startup.recycle_now=true; + TelnetRecycle->Enabled=false; + } +} +//--------------------------------------------------------------------------- + +void __fastcall TMainForm::FileEditTextFilesClick(TObject *Sender) +{ + TOpenDialog* dlg=new TOpenDialog((TComponent*)Sender); + + dlg->Options << ofNoChangeDir; + dlg->Filter = "Text files (*.txt)|*.TXT" + "|All files|*.*"; + dlg->InitialDir=cfg.text_dir; + if(dlg->Execute()==true) + EditFile(dlg->FileName.c_str()); + delete dlg; +} +//--------------------------------------------------------------------------- + +void __fastcall TMainForm::BBSEditBajaMenuItemClick(TObject *Sender) +{ + TOpenDialog* dlg=new TOpenDialog((TComponent*)Sender); + + dlg->Options << ofNoChangeDir; + dlg->Filter = "Baja Source Code (*.src)|*.SRC"; + dlg->InitialDir=cfg.exec_dir; + if(dlg->Execute()==true) { + Application->CreateForm(__classid(TTextFileEditForm), &TextFileEditForm); + TextFileEditForm->Filename=AnsiString(dlg->FileName); + TextFileEditForm->Caption="Edit"; + if(TextFileEditForm->ShowModal()==mrOk) { + /* Compile Baja Source File (requires Baja v2.33+) */ + char cmdline[512]; + sprintf(cmdline,"%sbaja -p %s",cfg.exec_dir,dlg->FileName); + WinExec(cmdline,SW_SHOW); + } + delete TextFileEditForm; + } + delete dlg; +} +//--------------------------------------------------------------------------- + +void __fastcall TMainForm::FileEditJavaScriptClick(TObject *Sender) +{ + TOpenDialog* dlg=new TOpenDialog((TComponent*)Sender); + + dlg->Options << ofNoChangeDir; + dlg->Filter = "JavaScript Files (*.js)|*.JS"; + dlg->InitialDir=cfg.exec_dir; + if(dlg->Execute()==true) + EditFile(dlg->FileName.c_str()); + delete dlg; +} +//--------------------------------------------------------------------------- + +void __fastcall TMainForm::FileEditConfigFilesClick(TObject *Sender) +{ + TOpenDialog* dlg=new TOpenDialog((TComponent*)Sender); + + dlg->Options << ofNoChangeDir; + dlg->Filter = "Configuration Files (*.cfg; *.ini; *.conf)|*.cfg;*.ini;*.conf"; + dlg->InitialDir=cfg.ctrl_dir; + if(dlg->Execute()==true) + EditFile(dlg->FileName.c_str()); + delete dlg; +} + +void __fastcall TMainForm::BBSEditFileClick(TObject *Sender) +{ + TOpenDialog* dlg=new TOpenDialog((TComponent*)Sender); + + dlg->Options << ofNoChangeDir; + dlg->Filter = "ANSI/Ctrl-A files (*.asc; *.msg; *.ans)|*.ASC;*.MSG;*.ANS" + "|All files|*.*"; + dlg->InitialDir=cfg.text_dir; + if(dlg->Execute()==true) { + Application->CreateForm(__classid(TTextFileEditForm), &TextFileEditForm); + TextFileEditForm->Filename=AnsiString(dlg->FileName); + TextFileEditForm->Caption="Edit"; + if(TextFileEditForm->ShowModal()==mrOk) { + Application->CreateForm(__classid(TPreviewForm), &PreviewForm); + PreviewForm->Filename=AnsiString(dlg->FileName); + PreviewForm->ShowModal(); + delete PreviewForm; + } + delete TextFileEditForm; + } + delete dlg; +} +//--------------------------------------------------------------------------- +bool GetServerLogLine(HANDLE& log, const char* name, char* line, size_t len) +{ + char fname[256]; + + if(log==INVALID_HANDLE_VALUE) { + sprintf(fname,"\\\\.\\mailslot\\%s.log",name); + log = CreateMailslot( + fname, // pointer to string for mailslot name + 0, // maximum message size + 0, // milliseconds before read time-out + NULL); // pointer to security structure + if(log==INVALID_HANDLE_VALUE) + return(false); + } + DWORD msgs=0; + if(!GetMailslotInfo( + log, // mailslot handle + NULL, // address of maximum message size + NULL, // address of size of next message + &msgs, // address of number of messages + NULL // address of read time-out + ) || !msgs) + return(false); + + DWORD rd=0; + if(!ReadFile( + log, // handle of file to read + line, // pointer to buffer that receives data + len-1, // number of bytes to read + &rd, // pointer to number of bytes read + NULL // pointer to structure for data + ) || !rd) + return(false); + + line[rd]=0; /* 0-terminate */ + + return(true); +} +//--------------------------------------------------------------------------- + +void __fastcall TMainForm::LogTimerTick(TObject *Sender) +{ + char line[1024]; + + while(GetServerLogLine(bbs_log,NTSVC_NAME_BBS,line,sizeof(line))) + bbs_lputs(NULL,LOG_INFO,line); + + while(GetServerLogLine(event_log,NTSVC_NAME_EVENT,line,sizeof(line))) + event_lputs(LOG_INFO,line); + + while(GetServerLogLine(ftp_log,NTSVC_NAME_FTP,line,sizeof(line))) + ftp_lputs(NULL,LOG_INFO,line); + + while(GetServerLogLine(web_log,NTSVC_NAME_WEB,line,sizeof(line))) + web_lputs(NULL,LOG_INFO,line); + + while(GetServerLogLine(mail_log,NTSVC_NAME_MAIL,line,sizeof(line))) + mail_lputs(NULL,LOG_INFO,line); + + while(GetServerLogLine(services_log,NTSVC_NAME_SERVICES,line,sizeof(line))) + service_lputs(NULL,LOG_INFO,line); + +} + +//--------------------------------------------------------------------------- +void CheckServiceStatus( + SC_HANDLE svc + ,SERVICE_STATUS* status + ,QUERY_SERVICE_CONFIG* &config + ,DWORD &config_size + ,TStaticText* text + ,TAction* start + ,TAction* stop + ,TAction* recycle + ,TProgressBar* bar + ) +{ + if(svc==NULL) + return; + + DWORD ret; + + if(!queryServiceConfig(svc,config,config_size,&ret)) { + if(GetLastError()==ERROR_INSUFFICIENT_BUFFER) { + config_size=ret; + if(config!=NULL) + free(config); + config = (QUERY_SERVICE_CONFIG*)malloc(config_size); + } + return; + } + + if(config->dwStartType==SERVICE_DISABLED) + return; + + if(!queryServiceStatus(svc,status)) { + text->Caption="QueryServiceStatus Error "; // + GetLastError()); + return; + } + + bool running=false; + + switch(status->dwCurrentState) { + case SERVICE_STOPPED: + text->Caption="Stopped NT Service"; + break; + case SERVICE_STOP_PENDING: + text->Caption="Stopping NT Service"; + break; + case SERVICE_RUNNING: + text->Caption="Running NT Service"; + running=true; + break; + case SERVICE_START_PENDING: + text->Caption="Starting NT Service"; + running=true; + break; + default: + text->Caption="!UNKNOWN: " + status->dwCurrentState; + break; + } + + start->Enabled=!running; + stop->Enabled=running; + recycle->Enabled=running; +} +//--------------------------------------------------------------------------- + +void __fastcall TMainForm::ServiceStatusTimerTick(TObject *Sender) +{ + if(queryServiceStatus==NULL || queryServiceConfig==NULL + || (bbs_svc==NULL + && ftp_svc==NULL + && web_svc==NULL + && mail_svc==NULL + && services_svc==NULL)) { + ServiceStatusTimer->Enabled=false; + return; + } + + CheckServiceStatus( + bbs_svc + ,&bbs_svc_status + ,bbs_svc_config + ,bbs_svc_config_size + ,TelnetForm->Status + ,TelnetStart + ,TelnetStop + ,TelnetRecycle + ,TelnetForm->ProgressBar + ); + CheckServiceStatus( + ftp_svc + ,&ftp_svc_status + ,ftp_svc_config + ,ftp_svc_config_size + ,FtpForm->Status + ,FtpStart + ,FtpStop + ,FtpRecycle + ,FtpForm->ProgressBar + ); + CheckServiceStatus( + web_svc + ,&web_svc_status + ,web_svc_config + ,web_svc_config_size + ,WebForm->Status + ,WebStart + ,WebStop + ,WebRecycle + ,WebForm->ProgressBar + ); + CheckServiceStatus( + mail_svc + ,&mail_svc_status + ,mail_svc_config + ,mail_svc_config_size + ,MailForm->Status + ,MailStart + ,MailStop + ,MailRecycle + ,MailForm->ProgressBar + ); + CheckServiceStatus( + services_svc + ,&services_svc_status + ,services_svc_config + ,services_svc_config_size + ,ServicesForm->Status + ,ServicesStart + ,ServicesStop + ,ServicesRecycle + ,NULL + ); + +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::EditFile(AnsiString filename, AnsiString Caption) +{ + if(!UseFileAssociations + || (int)ShellExecute(Handle, "edit", filename.c_str(), NULL,NULL,SW_SHOWDEFAULT)<=32) { + Application->CreateForm(__classid(TTextFileEditForm), &TextFileEditForm); + TextFileEditForm->Filename=filename; + TextFileEditForm->Caption=Caption; + TextFileEditForm->ShowModal(); + delete TextFileEditForm; + } +} +//--------------------------------------------------------------------------- +void __fastcall TMainForm::ViewFile(AnsiString filename, AnsiString Caption) +{ + if(!UseFileAssociations + || (int)ShellExecute(Handle, "open", filename.c_str(), NULL,NULL,SW_SHOWDEFAULT)<=32) { + Application->CreateForm(__classid(TTextFileEditForm), &TextFileEditForm); + TextFileEditForm->Filename=filename; + TextFileEditForm->Caption=Caption; + TextFileEditForm->Memo->ReadOnly=true; + TextFileEditForm->ShowModal(); + delete TextFileEditForm; + } +} +//--------------------------------------------------------------------------- +