1618 lines
35 KiB
C
1618 lines
35 KiB
C
// Chat Server for BPQ32 Packet Switch
|
|
//
|
|
//
|
|
// Based on MailChat Version 1.4.48.1
|
|
|
|
// Add Configurable SYSOP Call
|
|
|
|
// Sept 2013
|
|
|
|
// If user tries to reconnect to same node, disconnect old session
|
|
|
|
// Changed to match changed user rec format in kernel
|
|
|
|
// Fix initialisation of Signoff Message
|
|
|
|
// Jan 2014
|
|
|
|
// Add UTF-8 support
|
|
|
|
// ????
|
|
|
|
// Get command from node, and allow topic to be selected on command line
|
|
// Validate HTML Pages
|
|
|
|
|
|
// Oct 2014 1.0.5.1
|
|
// Fix occasional crash in terminal part line processing
|
|
|
|
// October 2015 1.0.6.1
|
|
// Recompiled for compatibility with WebMail
|
|
|
|
// Feb 2016 1.0.7.1
|
|
// Send Chat Map INFO on Startup
|
|
// Add Welcome Message to Web Config
|
|
|
|
// July 2017 1.0.8.1
|
|
// Fix Keepalives in Linux version
|
|
|
|
// November 2018 1.0.9.1
|
|
// Recompiled for Web Interface changes in Node
|
|
|
|
// January 2019 1.0.10.1
|
|
// Move Config from Registry to File BPQChatServer 1.cfg
|
|
|
|
// January 2019 1.0.10.2
|
|
// Fix errors in chat config file names and locations
|
|
|
|
// December 2020 1.0.11.1
|
|
|
|
// Send INFO to Map every hour
|
|
// Remove CMD_TO_APPL flag from Applflags
|
|
|
|
// October 2021 1.0.11.2
|
|
// Recompiled for Web Interface changes in Node
|
|
|
|
// February 2022 1.0.12.3 Renumbered to 6.0.23.1 to match Node
|
|
// Add option for user defined help file
|
|
// Add Connect Scripts
|
|
// Improve connect timeouts and add link validation polls
|
|
|
|
// Version 6.0.24.1 ??
|
|
|
|
// Restore CMD_TO_APPL flag to Applflags (13)
|
|
// Check for and remove names set to *RTL
|
|
// Add option to run user program when chat user connects (27)
|
|
// Add History (28)
|
|
// Add connect scripts to config page text (31)
|
|
// Fix History (31)
|
|
// Stop buffer overflow in History
|
|
// Allow /History to be shortened to /Hi (45)
|
|
// Fix extra r charater in Chat Config Web Page
|
|
|
|
#include "BPQChat.h"
|
|
#include "Dbghelp.h"
|
|
|
|
#define CHAT
|
|
#include "Versions.h"
|
|
|
|
#define LIBCONFIG_STATIC
|
|
#include "libconfig.h"
|
|
|
|
#include "GetVersion.h"
|
|
|
|
#define MAX_LOADSTRING 100
|
|
|
|
BOOL WINE = FALSE;
|
|
UINT BPQMsg;
|
|
|
|
HKEY REGTREE = HKEY_LOCAL_MACHINE; // Default
|
|
char * REGTREETEXT = "HKEY_LOCAL_MACHINE";
|
|
|
|
// Global Variables:
|
|
HINSTANCE hInst; // current instance
|
|
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
|
|
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
|
|
|
|
int LastVer[4] = {0, 0, 0, 0}; // In case we need to do somthing the first time a version is run
|
|
|
|
HWND MainWnd;
|
|
HWND hWndSess;
|
|
RECT MainRect;
|
|
HMENU hActionMenu;
|
|
static HMENU hMenu;
|
|
HMENU hDisMenu; // Disconnect Menu Handle
|
|
HMENU hFWDMenu; // Forward Menu Handle
|
|
|
|
int SessX, SessY, SessWidth; // Params for Session Window
|
|
|
|
char szBuff[80];
|
|
|
|
#define MaxSockets 64
|
|
|
|
extern ChatCIRCUIT ChatConnections[MaxSockets+1];
|
|
|
|
struct SEM ChatSemaphore = {0, 0};
|
|
|
|
struct SEM AllocSemaphore = {0, 0};
|
|
|
|
struct SEM ConSemaphore = {0, 0};
|
|
|
|
struct SEM OutputSEM = {0, 0};
|
|
|
|
struct UserInfo ** UserRecPtr=NULL;
|
|
int NumberofUsers=0;
|
|
|
|
struct UserInfo * BBSChain = NULL; // Chain of users that are BBSes
|
|
|
|
struct MsgInfo ** MsgHddrPtr=NULL;
|
|
int NumberofMessages=0;
|
|
|
|
int FirstMessageIndextoForward=0; // Lowest Message wirh a forward bit set - limits search
|
|
|
|
BOOL cfgMinToTray;
|
|
|
|
BOOL DisconnectOnClose=FALSE;
|
|
|
|
char PasswordMsg[100]="Password:";
|
|
|
|
char cfgHOSTPROMPT[100];
|
|
|
|
char cfgCTEXT[100];
|
|
|
|
char cfgLOCALECHO[100];
|
|
|
|
char AttemptsMsg[] = "Too many attempts - Disconnected\r\r";
|
|
char disMsg[] = "Disconnected by SYSOP\r\r";
|
|
|
|
char LoginMsg[]="user:";
|
|
|
|
char BlankCall[]=" ";
|
|
|
|
char ChatSYSOPCall[50];
|
|
|
|
ULONG BBSApplMask;
|
|
ULONG ChatApplMask;
|
|
|
|
int BBSApplNum=0;
|
|
int ChatApplNum=0;
|
|
|
|
extern int NumberofChatStreams;
|
|
|
|
//int StartStream=0;
|
|
|
|
extern int MaxChatStreams;
|
|
|
|
char ChatSID[]="[BPQChatServer-%d.%d.%d.%d]\r";
|
|
|
|
extern char ChatWelcomeMsg[1000];
|
|
|
|
char NewUserPrompt[100]="Please enter your Name\r>\r";
|
|
|
|
char ChatSignoffMsg[100];
|
|
|
|
char AbortedMsg[100]="\rOutput aborted\r";
|
|
|
|
char BaseDir[MAX_PATH];
|
|
|
|
char RlineVer[50];
|
|
|
|
BOOL KISSOnly = FALSE;
|
|
|
|
UCHAR * OtherNodes=NULL;
|
|
char OtherNodesList[1000];
|
|
|
|
char BPQDirectory[260];
|
|
|
|
extern char Position[81];
|
|
extern char PopupText[260];
|
|
extern int PopupMode;
|
|
|
|
int Bells, FlashOnBell, StripLF, WarnWrap, WrapInput, FlashOnConnect, CloseWindowOnBye;
|
|
|
|
char Version[32];
|
|
char ConsoleSize[32];
|
|
char MonitorSize[32];
|
|
char DebugSize[32];
|
|
char WindowSize[32];
|
|
|
|
extern config_setting_t * group;
|
|
|
|
int ProgramErrors = 0;
|
|
|
|
// Forward declarations of functions included in this code module:
|
|
ATOM MyRegisterClass(HINSTANCE hInstance);
|
|
ATOM RegisterMainWindowClass(HINSTANCE hInstance);
|
|
BOOL InitInstance(HINSTANCE, int);
|
|
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
|
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
|
|
INT_PTR CALLBACK ChatMapDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR CALLBACK ConfigWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
INT_PTR CALLBACK ChatColourDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
|
|
VOID SaveWindowConfig();
|
|
void ChatWriteLogLine(ChatCIRCUIT * conn, int Flag, char * Msg, int MsgLen, int Flags);
|
|
char * lookupuser(char * call);
|
|
BOOL GetChatConfig(char * ConfigName);
|
|
BOOL SaveChatConfigFile(char * ConfigName);
|
|
BOOL GetConfigFromRegistry();
|
|
VOID SaveStringValue(config_setting_t * group, char * name, char * value);
|
|
VOID SaveIntValue(config_setting_t * group, char * name, int value);
|
|
VOID SaveChatConfig(HWND hDlg);
|
|
BOOL CreateChatPipeThread();
|
|
VOID WriteMiniDump();
|
|
|
|
struct _EXCEPTION_POINTERS exinfox;
|
|
|
|
CONTEXT ContextRecord;
|
|
EXCEPTION_RECORD ExceptionRecord;
|
|
|
|
DWORD Stack[16];
|
|
|
|
BOOL Restarting = FALSE;
|
|
|
|
typedef int (WINAPI FAR *FARPROCX)();
|
|
FARPROCX pRunEventProgram;
|
|
|
|
int Dump_Process_State(struct _EXCEPTION_POINTERS * exinfo, char * Msg)
|
|
{
|
|
unsigned int SPPtr;
|
|
unsigned int SPVal;
|
|
|
|
memcpy(&ContextRecord, exinfo->ContextRecord, sizeof(ContextRecord));
|
|
memcpy(&ExceptionRecord, exinfo->ExceptionRecord, sizeof(ExceptionRecord));
|
|
|
|
SPPtr = ContextRecord.Esp;
|
|
|
|
Debugprintf("BPQChat *** Program Error %x at %x in %s",
|
|
ExceptionRecord.ExceptionCode, ExceptionRecord.ExceptionAddress, Msg);
|
|
|
|
|
|
__asm{
|
|
|
|
mov eax, SPPtr
|
|
mov SPVal,eax
|
|
lea edi,Stack
|
|
mov esi,eax
|
|
mov ecx,64
|
|
rep movsb
|
|
|
|
}
|
|
|
|
Debugprintf("EAX %x EBX %x ECX %x EDX %x ESI %x EDI %x ESP %x",
|
|
ContextRecord.Eax, ContextRecord.Ebx, ContextRecord.Ecx,
|
|
ContextRecord.Edx, ContextRecord.Esi, ContextRecord.Edi, SPVal);
|
|
|
|
Debugprintf("Stack:");
|
|
|
|
Debugprintf("%08x %08x %08x %08x %08x %08x %08x %08x %08x ",
|
|
SPVal, Stack[0], Stack[1], Stack[2], Stack[3], Stack[4], Stack[5], Stack[6], Stack[7]);
|
|
|
|
Debugprintf("%08x %08x %08x %08x %08x %08x %08x %08x %08x ",
|
|
SPVal+32, Stack[8], Stack[9], Stack[10], Stack[11], Stack[12], Stack[13], Stack[14], Stack[15]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void myInvalidParameterHandler(const wchar_t* expression,
|
|
const wchar_t* function,
|
|
const wchar_t* file,
|
|
unsigned int line,
|
|
uintptr_t pReserved)
|
|
{
|
|
Logprintf(LOG_DEBUGx, NULL, '!', "*** Error **** C Run Time Invalid Parameter Handler Called");
|
|
|
|
if (expression && function && file)
|
|
{
|
|
Logprintf(LOG_DEBUGx, NULL, '!', "Expression = %S", expression);
|
|
Logprintf(LOG_DEBUGx, NULL, '!', "Function %S", function);
|
|
Logprintf(LOG_DEBUGx, NULL, '!', "File %S Line %d", file, line);
|
|
}
|
|
}
|
|
|
|
char ChatConfigName[MAX_PATH];
|
|
char Session[20] = "Server 1";
|
|
|
|
BOOL UsingingRegConfig = FALSE;
|
|
|
|
// If program gets too many program errors, it will restart itself and shut down
|
|
|
|
VOID CheckProgramErrors()
|
|
{
|
|
STARTUPINFO SInfo; // pointer to STARTUPINFO
|
|
PROCESS_INFORMATION PInfo; // pointer to PROCESS_INFORMATION
|
|
char ProgName[256];
|
|
|
|
if (Restarting)
|
|
exit(0); // Make sure can't loop in restarting
|
|
|
|
ProgramErrors++;
|
|
|
|
if (ProgramErrors > 25)
|
|
{
|
|
char Command[30];
|
|
|
|
Restarting = TRUE;
|
|
|
|
Logprintf(LOG_DEBUGx, NULL, '!', "Too Many Program Errors - Closing");
|
|
|
|
if (cfgMinToTray)
|
|
{
|
|
DeleteTrayMenuItem(MainWnd);
|
|
if (ConsHeader[0]->hConsole)
|
|
DeleteTrayMenuItem(ConsHeader[0]->hConsole);
|
|
if (ConsHeader[1]->hConsole)
|
|
DeleteTrayMenuItem(ConsHeader[1]->hConsole);
|
|
if (hMonitor)
|
|
DeleteTrayMenuItem(hMonitor);
|
|
if (hDebug)
|
|
DeleteTrayMenuItem(hDebug);
|
|
}
|
|
|
|
SInfo.cb=sizeof(SInfo);
|
|
SInfo.lpReserved=NULL;
|
|
SInfo.lpDesktop=NULL;
|
|
SInfo.lpTitle=NULL;
|
|
SInfo.dwFlags=0;
|
|
SInfo.cbReserved2=0;
|
|
SInfo.lpReserved2=NULL;
|
|
|
|
GetModuleFileName(NULL, ProgName, 256);
|
|
|
|
Debugprintf("Attempting to Restart %s", ProgName);
|
|
|
|
wsprintf(Command, "WAIT %s", Session);
|
|
|
|
CreateProcess(ProgName, Command, NULL, NULL, FALSE, 0, NULL, NULL, &SInfo, &PInfo);
|
|
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
VOID WriteMiniDump()
|
|
{
|
|
#ifdef WIN32
|
|
|
|
HANDLE hFile;
|
|
BOOL ret;
|
|
char FN[256];
|
|
|
|
sprintf(FN, "%s/Logs/MiniDump%x.dmp", GetBPQDirectory(), time(NULL));
|
|
|
|
hFile = CreateFile(FN, GENERIC_READ | GENERIC_WRITE,
|
|
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
|
|
{
|
|
// Create the minidump
|
|
|
|
ret = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
|
|
hFile, MiniDumpNormal, 0, 0, 0 );
|
|
|
|
if(!ret)
|
|
Debugprintf("MiniDumpWriteDump failed. Error: %u", GetLastError());
|
|
else
|
|
Debugprintf("Minidump %s created.", FN);
|
|
CloseHandle(hFile);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
HKEY OpenReg()
|
|
{
|
|
char Key[100];
|
|
HKEY hKey = 0;
|
|
int disp;
|
|
|
|
sprintf(Key, "SOFTWARE\\G8BPQ\\BPQ32\\Chat\\%s", Session);
|
|
|
|
RegCreateKeyEx(REGTREE, Key, 0, 0, 0, KEY_ALL_ACCESS, NULL, &hKey, &disp);
|
|
|
|
return hKey;
|
|
}
|
|
|
|
int regGetIntValue(char * Key, int Default)
|
|
{
|
|
HKEY hKey = OpenReg();
|
|
int Type, Vallen = 4;
|
|
int Val = Default;
|
|
|
|
RegQueryValueEx(hKey ,Key, 0, &Type, (UCHAR *)&Val, (ULONG *)&Vallen);
|
|
RegCloseKey(hKey);
|
|
|
|
return Val;
|
|
}
|
|
|
|
BOOL regGetStringValue(char * Key, char * Value, int Len)
|
|
{
|
|
HKEY hKey = OpenReg();
|
|
int Type, Vallen = Len;
|
|
int ret;
|
|
|
|
ret = RegQueryValueEx(hKey ,Key, 0, &Type, (UCHAR *)Value, (ULONG *)&Vallen);
|
|
if (ret != ERROR_SUCCESS)
|
|
return FALSE;
|
|
|
|
RegCloseKey(hKey);
|
|
return TRUE;
|
|
}
|
|
|
|
int APIENTRY WinMain(HINSTANCE hInstance,
|
|
HINSTANCE hPrevInstance,
|
|
LPTSTR lpCmdLine,
|
|
int nCmdShow)
|
|
{
|
|
MSG msg;
|
|
HACCEL hAccelTable;
|
|
int BPQStream, n;
|
|
struct _EXCEPTION_POINTERS exinfo;
|
|
_invalid_parameter_handler oldHandler, newHandler;
|
|
char Msg[100];
|
|
int i = 60;
|
|
char * ptr;
|
|
|
|
int nCodePage = GetACP();
|
|
|
|
if (strstr(lpCmdLine, "WAIT")) // If AutoRestart then Delay 60 Secs
|
|
{
|
|
hWnd = CreateWindow("STATIC", "Chat Restarting after Failure - Please Wait", 0,
|
|
CW_USEDEFAULT, 100, 550, 70,
|
|
NULL, NULL, hInstance, NULL);
|
|
|
|
ShowWindow(hWnd, nCmdShow);
|
|
|
|
while (i-- > 0)
|
|
{
|
|
wsprintf(Msg, "Chat Restarting after Failure - Please Wait %d secs.", i);
|
|
SetWindowText(hWnd, Msg);
|
|
|
|
Sleep(1000);
|
|
}
|
|
|
|
DestroyWindow(hWnd);
|
|
}
|
|
|
|
ptr = strstr(_strupr(lpCmdLine), "SERVER");
|
|
|
|
if (ptr)
|
|
strcpy(Session, ptr);
|
|
|
|
_strlwr(&Session[1]);
|
|
|
|
strcpy(BPQDirectory, GetBPQDirectory());
|
|
|
|
__try {
|
|
|
|
// Trap CRT Errors
|
|
|
|
newHandler = myInvalidParameterHandler;
|
|
oldHandler = _set_invalid_parameter_handler(newHandler);
|
|
|
|
// Initialize global strings
|
|
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
|
|
LoadString(hInstance, IDC_BPQMailChat, szWindowClass, MAX_LOADSTRING);
|
|
MyRegisterClass(hInstance);
|
|
|
|
// Perform application initialization:
|
|
|
|
if (!InitInstance (hInstance, nCmdShow))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_BPQMailChat));
|
|
|
|
// Main message loop:
|
|
|
|
Logprintf(LOG_CHAT, NULL, '!', "Program Starting");
|
|
|
|
} My__except_Routine("Init");
|
|
|
|
while (GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
__try
|
|
{
|
|
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
#define EXCEPTMSG "GetMessageLoop"
|
|
#include "StdExcept.c"
|
|
|
|
CheckProgramErrors();
|
|
}
|
|
}
|
|
|
|
__try
|
|
{
|
|
for (n = 0; n < NumberofChatStreams; n++)
|
|
{
|
|
BPQStream=ChatConnections[n].BPQStream;
|
|
|
|
if (BPQStream)
|
|
{
|
|
SetAppl(BPQStream, 0, 0);
|
|
Disconnect(BPQStream);
|
|
DeallocateStream(BPQStream);
|
|
}
|
|
}
|
|
|
|
CloseConsole(-2);
|
|
|
|
ClearChatLinkStatus();
|
|
SendChatLinkStatus();
|
|
|
|
hWnd = CreateWindow("STATIC", "Chat Closing - Please Wait", 0,
|
|
150, 200, 350, 40, NULL, NULL, hInstance, NULL);
|
|
|
|
ShowWindow(hWnd, nCmdShow);
|
|
|
|
Sleep(1000); // A bit of time for links to close
|
|
|
|
SendChatLinkStatus(); // Send again to reduce chance of being missed
|
|
|
|
Sleep(2000);
|
|
|
|
DestroyWindow(hWnd);
|
|
|
|
if (ConsHeader[0]->hConsole)
|
|
DestroyWindow(ConsHeader[0]->hConsole);
|
|
if (ConsHeader[1]->hConsole)
|
|
DestroyWindow(ConsHeader[1]->hConsole);
|
|
if (hMonitor)
|
|
DestroyWindow(hMonitor);
|
|
if (hDebug)
|
|
DestroyWindow(hDebug);
|
|
|
|
if (cfgMinToTray)
|
|
{
|
|
DeleteTrayMenuItem(MainWnd);
|
|
if (ConsHeader[0]->hConsole)
|
|
DeleteTrayMenuItem(ConsHeader[0]->hConsole);
|
|
if (ConsHeader[1]->hConsole)
|
|
DeleteTrayMenuItem(ConsHeader[1]->hConsole);
|
|
if (hMonitor)
|
|
DeleteTrayMenuItem(hMonitor);
|
|
if (hDebug)
|
|
DeleteTrayMenuItem(hDebug);
|
|
}
|
|
|
|
|
|
FreeChatMemory();
|
|
|
|
n = 0;
|
|
|
|
_CrtDumpMemoryLeaks();
|
|
|
|
}
|
|
My__except_Routine("Close Processing");
|
|
|
|
SaveWindowConfig();
|
|
|
|
CloseBPQ32(); // Close Ext Drivers if last bpq32 process
|
|
|
|
SaveChatConfigFile(ChatConfigName);
|
|
|
|
return (int) msg.wParam;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// FUNCTION: MyRegisterClass()
|
|
//
|
|
// PURPOSE: Registers the window class.
|
|
//
|
|
// COMMENTS:
|
|
//
|
|
// This function and its usage are only necessary if you want this code
|
|
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
|
|
// function that was added to Windows 95. It is important to call this function
|
|
// so that the application will get 'well formed' small icons associated
|
|
// with it.
|
|
//
|
|
//
|
|
#define BGCOLOUR RGB(236,233,216)
|
|
//#define BGCOLOUR RGB(245,245,245)
|
|
|
|
HBRUSH bgBrush;
|
|
|
|
ATOM MyRegisterClass(HINSTANCE hInstance)
|
|
{
|
|
WNDCLASSEX wcex;
|
|
|
|
bgBrush = CreateSolidBrush(BGCOLOUR);
|
|
|
|
wcex.cbSize = sizeof(WNDCLASSEX);
|
|
|
|
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
|
wcex.lpfnWndProc = WndProc;
|
|
wcex.cbClsExtra = 0;
|
|
wcex.cbWndExtra = DLGWINDOWEXTRA;
|
|
wcex.hInstance = hInstance;
|
|
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(BPQICON));
|
|
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wcex.hbrBackground = bgBrush;
|
|
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_BPQMailChat);
|
|
wcex.lpszClassName = szWindowClass;
|
|
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(BPQICON));
|
|
|
|
return RegisterClassEx(&wcex);
|
|
}
|
|
|
|
|
|
//
|
|
// FUNCTION: InitInstance(HINSTANCE, int)
|
|
//
|
|
// PURPOSE: Saves instance handle and creates main window
|
|
//
|
|
// COMMENTS:
|
|
//
|
|
// In this function, we save the instance handle in a global variable and
|
|
// create and display the main program window.
|
|
//
|
|
|
|
HWND hWnd;
|
|
|
|
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
|
|
{
|
|
char Title[80];
|
|
WSADATA WsaData;
|
|
HMENU hTopMenu; // handle of menu
|
|
HKEY hKey=0;
|
|
int retCode;
|
|
RECT InitRect;
|
|
RECT SessRect;
|
|
struct _EXCEPTION_POINTERS exinfo;
|
|
struct stat STAT;
|
|
|
|
REGTREE = GetRegistryKey();
|
|
REGTREETEXT = GetRegistryKeyText();
|
|
|
|
// See if running under WINE
|
|
|
|
retCode = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine", 0, KEY_QUERY_VALUE, &hKey);
|
|
|
|
if (retCode == ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hKey);
|
|
WINE =TRUE;
|
|
Debugprintf("Running under WINE");
|
|
}
|
|
|
|
if (Session[7] == '1')
|
|
sprintf(ChatConfigName, "%s/chatconfig.cfg", GetBPQDirectory());
|
|
else
|
|
sprintf(ChatConfigName, "%s/chatconfig%s.cfg", GetBPQDirectory(), Session);
|
|
|
|
// Set up file and directory names
|
|
|
|
strcpy(BaseDir, GetBPQDirectory());
|
|
|
|
strcpy(RtUsr, BaseDir);
|
|
strcat(RtUsr, "/ChatUsers.txt");
|
|
|
|
strcpy(RtUsrTemp, BaseDir);
|
|
strcat(RtUsrTemp, "/ChatUsers.tmp");
|
|
|
|
strcpy(RtKnown, BaseDir);
|
|
strcat(RtKnown, "/RTKnown.txt");
|
|
|
|
// Debugprintf("Users %s", RtUsr);
|
|
|
|
UsingingRegConfig = FALSE;
|
|
|
|
// if config file exists use it else try to get from Registry
|
|
|
|
if (stat(ChatConfigName, &STAT) == -1)
|
|
{
|
|
UsingingRegConfig = TRUE;
|
|
|
|
if (GetConfigFromRegistry())
|
|
{
|
|
SaveChatConfigFile(ChatConfigName);
|
|
}
|
|
else
|
|
{
|
|
int retCode;
|
|
char msg[80];
|
|
|
|
sprintf(msg, "No configuration found - Dummy Config created");
|
|
|
|
retCode = MessageBox(NULL, msg, "BPQChat", MB_OKCANCEL);
|
|
|
|
if (retCode == IDCANCEL)
|
|
return FALSE;
|
|
|
|
SaveChatConfigFile(ChatConfigName);
|
|
}
|
|
}
|
|
|
|
GetChatConfig(ChatConfigName);
|
|
|
|
// Get Window Sizes
|
|
|
|
sscanf(WindowSize,"%d,%d,%d,%d",&MainRect.left,&MainRect.right,&MainRect.top,&MainRect.bottom);
|
|
sscanf(DebugSize, "%d,%d,%d,%d", &DebugRect.left, &DebugRect.right, &DebugRect.top, &DebugRect.bottom);
|
|
sscanf(MonitorSize, "%d,%d,%d,%d", &MonitorRect.left, &MonitorRect.right, &MonitorRect.top, &MonitorRect.bottom);
|
|
sscanf(ConsoleSize, "%d,%d,%d,%d", &ConsoleRect.left, &ConsoleRect.right, &ConsoleRect.top, &ConsoleRect.bottom);
|
|
|
|
hInst = hInstance;
|
|
|
|
hWnd=CreateDialog(hInst,szWindowClass,0,NULL);
|
|
|
|
if (!hWnd)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
MainWnd=hWnd;
|
|
|
|
if (MainRect.right < 100 || MainRect.bottom < 100)
|
|
{
|
|
GetWindowRect(hWnd, &MainRect);
|
|
}
|
|
|
|
MoveWindow(hWnd,MainRect.left,MainRect.top, MainRect.right-MainRect.left, MainRect.bottom-MainRect.top, TRUE);
|
|
|
|
GetVersionInfo(NULL);
|
|
|
|
wsprintf(Title,"G8BPQ Chat Server Version %s %s", VersionString, Session);
|
|
|
|
SetWindowText(hWnd,Title);
|
|
|
|
hWndSess = GetDlgItem(hWnd, 100);
|
|
|
|
GetWindowRect(hWnd, &InitRect);
|
|
GetWindowRect(hWndSess, &SessRect);
|
|
|
|
SessX = SessRect.left - InitRect.left ;
|
|
SessY = SessRect.top -InitRect.top;
|
|
SessWidth = SessRect.right - SessRect.left;
|
|
|
|
// Get handles fou updating menu items
|
|
|
|
hTopMenu=GetMenu(MainWnd);
|
|
hActionMenu=GetSubMenu(hTopMenu,0);
|
|
|
|
// hFWDMenu=GetSubMenu(hActionMenu,0);
|
|
hMenu=GetSubMenu(hActionMenu,0);
|
|
hDisMenu=GetSubMenu(hActionMenu,1);
|
|
|
|
CheckTimer();
|
|
|
|
cfgMinToTray = GetMinimizetoTrayFlag();
|
|
|
|
if ((nCmdShow == SW_SHOWMINIMIZED) || (nCmdShow == SW_SHOWMINNOACTIVE))
|
|
if (cfgMinToTray)
|
|
{
|
|
ShowWindow(hWnd, SW_HIDE);
|
|
}
|
|
else
|
|
{
|
|
ShowWindow(hWnd, nCmdShow);
|
|
}
|
|
else
|
|
ShowWindow(hWnd, nCmdShow);
|
|
|
|
UpdateWindow(hWnd);
|
|
|
|
WSAStartup(MAKEWORD(2, 0), &WsaData);
|
|
|
|
__try {
|
|
|
|
return Initialise();
|
|
|
|
}My__except_Routine("Initialise");
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
|
|
//
|
|
// PURPOSE: Processes messages for the main window.
|
|
//
|
|
//
|
|
|
|
|
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int wmId, wmEvent;
|
|
PAINTSTRUCT ps;
|
|
HDC hdc;
|
|
int state,change, i;
|
|
ChatCIRCUIT * conn;
|
|
struct _EXCEPTION_POINTERS exinfo;
|
|
|
|
|
|
if (message == BPQMsg)
|
|
{
|
|
if (lParam & BPQDataAvail)
|
|
{
|
|
// Dont trap error at this level - let Node error handler pick it up
|
|
// __try
|
|
// {
|
|
DoReceivedData(wParam);
|
|
// }
|
|
// My__except_Routine("DoReceivedData")
|
|
return 0;
|
|
}
|
|
if (lParam & BPQStateChange)
|
|
{
|
|
// Get current Session State. Any state changed is ACK'ed
|
|
// automatically. See BPQHOST functions 4 and 5.
|
|
|
|
__try
|
|
{
|
|
SessionState(wParam, &state, &change);
|
|
|
|
if (change == 1)
|
|
{
|
|
if (state == 1) // Connected
|
|
{
|
|
GetSemaphore(&ConSemaphore, 0);
|
|
__try {Connected(wParam);}
|
|
My__except_Routine("Connected");
|
|
FreeSemaphore(&ConSemaphore);
|
|
}
|
|
else
|
|
{
|
|
GetSemaphore(&ConSemaphore, 0);
|
|
__try{Disconnected(wParam);}
|
|
My__except_Routine("Disconnected");
|
|
FreeSemaphore(&ConSemaphore);
|
|
}
|
|
}
|
|
}
|
|
My__except_Routine("DoStateChange");
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
switch (message)
|
|
{
|
|
|
|
case WM_KEYUP:
|
|
|
|
switch (wParam)
|
|
{
|
|
case VK_F3:
|
|
CreateConsole(-2);
|
|
return 0;
|
|
|
|
case VK_F4:
|
|
CreateMonitor();
|
|
return 0;
|
|
|
|
case VK_F5:
|
|
CreateDebugWindow();
|
|
return 0;
|
|
|
|
case VK_TAB:
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
return 0;
|
|
|
|
case WM_TIMER:
|
|
|
|
if (wParam == 1) // Slow = 10 secs
|
|
{
|
|
__try
|
|
{
|
|
RefreshMainWindow();
|
|
CheckTimer();
|
|
ChatTimer();
|
|
}
|
|
My__except_Routine("Slow Timer");
|
|
}
|
|
else
|
|
__try
|
|
{
|
|
TrytoSend();
|
|
}
|
|
My__except_Routine("TrytoSend");
|
|
|
|
return (0);
|
|
|
|
|
|
case WM_CTLCOLORDLG:
|
|
return (LONG)bgBrush;
|
|
|
|
case WM_CTLCOLORSTATIC:
|
|
{
|
|
HDC hdcStatic = (HDC)wParam;
|
|
SetTextColor(hdcStatic, RGB(0, 0, 0));
|
|
SetBkMode(hdcStatic, TRANSPARENT);
|
|
return (LONG)bgBrush;
|
|
}
|
|
|
|
case WM_INITMENUPOPUP:
|
|
|
|
if (wParam == (WPARAM)hActionMenu)
|
|
{
|
|
if (IsClipboardFormatAvailable(CF_TEXT))
|
|
EnableMenuItem(hActionMenu,ID_ACTIONS_SENDMSGFROMCLIPBOARD, MF_BYCOMMAND | MF_ENABLED);
|
|
else
|
|
EnableMenuItem(hActionMenu,ID_ACTIONS_SENDMSGFROMCLIPBOARD, MF_BYCOMMAND | MF_GRAYED );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
if (wParam == (WPARAM)hDisMenu)
|
|
{
|
|
// Set up Disconnect Menu
|
|
|
|
ChatCIRCUIT * conn;
|
|
char MenuLine[30];
|
|
int n;
|
|
|
|
for (n = 0; n <= NumberofChatStreams-1; n++)
|
|
{
|
|
conn=&ChatConnections[n];
|
|
|
|
RemoveMenu(hDisMenu, IDM_DISCONNECT + n, MF_BYCOMMAND);
|
|
|
|
if (conn->Active)
|
|
{
|
|
sprintf_s(MenuLine, 30, "%d %s", conn->BPQStream, conn->Callsign);
|
|
AppendMenu(hDisMenu, MF_STRING, IDM_DISCONNECT + n, MenuLine);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
|
|
case WM_COMMAND:
|
|
wmId = LOWORD(wParam);
|
|
wmEvent = HIWORD(wParam);
|
|
// Parse the menu selections:
|
|
|
|
if (wmEvent == LBN_DBLCLK)
|
|
|
|
break;
|
|
|
|
if (wmId >= IDM_DISCONNECT && wmId < IDM_DISCONNECT+MaxSockets+1)
|
|
{
|
|
// disconnect user
|
|
|
|
conn=&ChatConnections[wmId-IDM_DISCONNECT];
|
|
|
|
if (conn->Active)
|
|
{
|
|
Disconnect(conn->BPQStream);
|
|
}
|
|
}
|
|
|
|
|
|
switch (wmId)
|
|
{
|
|
|
|
case IDM_LOGCHAT:
|
|
|
|
ToggleParam(hMenu, hWnd, &LogCHAT, IDM_LOGCHAT);
|
|
break;
|
|
|
|
|
|
case IDM_CHATCONSOLE:
|
|
|
|
CreateConsole(-2);
|
|
break;
|
|
|
|
case IDM_MONITOR:
|
|
|
|
CreateMonitor();
|
|
break;
|
|
|
|
case IDM_DEBUG:
|
|
CreateDebugWindow();
|
|
break;
|
|
|
|
case IDM_ABOUT:
|
|
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
|
|
break;
|
|
|
|
case ID_HELP_ONLINEHELP:
|
|
|
|
ShellExecute(hWnd,"open",
|
|
"http://www.cantab.net/users/john.wiseman/Documents/BPQ%20Mail%20and%20Chat%20Server.htm",
|
|
"", NULL, SW_SHOWNORMAL);
|
|
|
|
break;
|
|
|
|
case IDM_CONFIG:
|
|
i = DialogBox(hInst, MAKEINTRESOURCE(CHAT_CONFIG), hWnd, ConfigWndProc);
|
|
i = WSAGetLastError();
|
|
break;
|
|
|
|
|
|
case IDM_EDITCHATCOLOURS:
|
|
DialogBox(hInst, MAKEINTRESOURCE(IDD_CHATCOLCONFIG), hWnd, ChatColourDialogProc);
|
|
break;
|
|
|
|
case ID_ACTIONS_UPDATECHATMAPINFO:
|
|
DialogBox(hInst, MAKEINTRESOURCE(IDD_UPDATECHATMAP), hWnd, ChatMapDialogProc);
|
|
break;
|
|
|
|
case IDM_EXIT:
|
|
DestroyWindow(hWnd);
|
|
break;
|
|
|
|
|
|
default:
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
}
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
|
|
if (wParam == SIZE_MINIMIZED)
|
|
if (cfgMinToTray)
|
|
return ShowWindow(hWnd, SW_HIDE);
|
|
|
|
return (0);
|
|
|
|
|
|
case WM_SIZING:
|
|
{
|
|
LPRECT lprc = (LPRECT) lParam;
|
|
int Height = lprc->bottom-lprc->top;
|
|
|
|
MoveWindow(hWndSess, 0, 30, SessWidth, Height - 100, TRUE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
case WM_PAINT:
|
|
hdc = BeginPaint(hWnd, &ps);
|
|
// TODO: Add any drawing code here...
|
|
EndPaint(hWnd, &ps);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
|
|
GetWindowRect(MainWnd, &MainRect); // For save soutine
|
|
if (ConsHeader[1]->hConsole)
|
|
GetWindowRect(ConsHeader[1]->hConsole, &ConsoleRect); // For save soutine
|
|
if (hMonitor)
|
|
GetWindowRect(hMonitor, &MonitorRect); // For save soutine
|
|
if (hDebug)
|
|
GetWindowRect(hDebug, &DebugRect); // For save soutine
|
|
|
|
KillTimer(hWnd,1);
|
|
KillTimer(hWnd,2);
|
|
PostQuitMessage(0);
|
|
break;
|
|
|
|
default:
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
INT_PTR CALLBACK ChatMapDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
char Msg[500];
|
|
int len;
|
|
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
|
|
SetDlgItemText(hDlg, IDC_MAPPOSITION, Position);
|
|
SetDlgItemText(hDlg, IDC_POPUPTEXT, PopupText);
|
|
|
|
SendDlgItemMessage(hDlg, IDC_CLICK, BM_SETCHECK, PopupMode , PopupMode);
|
|
SendDlgItemMessage(hDlg, IDC_HOVER, BM_SETCHECK, !PopupMode , !PopupMode);
|
|
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
|
|
switch LOWORD(wParam)
|
|
{
|
|
case IDSENDTOMAP:
|
|
|
|
GetDlgItemText(hDlg, IDC_MAPPOSITION, Position, 80);
|
|
GetDlgItemText(hDlg, IDC_POPUPTEXT, PopupText, 250);
|
|
|
|
PopupMode = SendDlgItemMessage(hDlg, IDC_CLICK, BM_GETCHECK, 0 ,0);
|
|
|
|
// if (AXIPPort)
|
|
{
|
|
len = wsprintf(Msg, "INFO %s|%s|%d|\r", Position, PopupText, PopupMode);
|
|
|
|
if (len < 256)
|
|
Send_MON_Datagram(Msg, len);
|
|
}
|
|
|
|
break;
|
|
|
|
case IDOK:
|
|
|
|
GetDlgItemText(hDlg, IDC_MAPPOSITION, Position, 80);
|
|
GetDlgItemText(hDlg, IDC_POPUPTEXT, PopupText, 250);
|
|
|
|
PopupMode = SendDlgItemMessage(hDlg, IDC_CLICK, BM_GETCHECK, 0 ,0);
|
|
|
|
case IDCANCEL:
|
|
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
return TRUE;
|
|
|
|
case IDC_MAPHELP:
|
|
|
|
ShellExecute(hDlg,"open",
|
|
"http://www.cantab.net/users/john.wiseman/Documents/BPQChatMap.htm",
|
|
"", NULL, SW_SHOWNORMAL);
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// Message handler for about box.
|
|
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
return (INT_PTR)TRUE;
|
|
|
|
case WM_COMMAND:
|
|
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
|
|
{
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
return (INT_PTR)TRUE;
|
|
}
|
|
return (INT_PTR)TRUE;
|
|
|
|
break;
|
|
}
|
|
return (INT_PTR)FALSE;
|
|
}
|
|
|
|
int RefreshMainWindow()
|
|
{
|
|
char msg[80];
|
|
ChatCIRCUIT * conn;
|
|
int i,n, SYSOPMsgs = 0, HeldMsgs = 0, SMTPMsgs = 0;
|
|
time_t now;
|
|
struct tm * tm;
|
|
char tim[20];
|
|
|
|
SendDlgItemMessage(MainWnd,100,LB_RESETCONTENT,0,0);
|
|
|
|
for (n = 0; n < NumberofChatStreams; n++)
|
|
{
|
|
conn=&ChatConnections[n];
|
|
|
|
if (!conn->Active)
|
|
{
|
|
strcpy(msg,"Idle");
|
|
}
|
|
else
|
|
{
|
|
if (conn->Flags & CHATLINK)
|
|
{
|
|
if (conn->u.link->supportsPolls)
|
|
i=sprintf_s(msg, sizeof(msg), "%-10s %-10s %2d %-10s%5d %4d",
|
|
"Chat Link", conn->u.link->alias, conn->BPQStream,
|
|
"", conn->OutputQueueLength - conn->OutputGetPointer, conn->u.link->RTT);
|
|
else
|
|
i=sprintf_s(msg, sizeof(msg), "%-10s %-10s %2d %-10s%5d",
|
|
"Chat Link", conn->u.link->alias, conn->BPQStream,
|
|
"", conn->OutputQueueLength - conn->OutputGetPointer);
|
|
|
|
}
|
|
else
|
|
if ((conn->Flags & CHATMODE) && conn->topic)
|
|
{
|
|
i=sprintf_s(msg, sizeof(msg), "%-10s %-10s %2d %-10s%5d",
|
|
conn->UserPointer->Name, conn->u.user->call, conn->BPQStream,
|
|
conn->topic->topic->name, conn->OutputQueueLength - conn->OutputGetPointer);
|
|
}
|
|
else
|
|
{
|
|
if (conn->UserPointer == 0)
|
|
strcpy(msg,"Logging in");
|
|
else
|
|
{
|
|
i=sprintf_s(msg, sizeof(msg), "%-10s %-10s %2d %-10s%5d",
|
|
conn->UserPointer->Name, conn->UserPointer->Call, conn->BPQStream,
|
|
"CHAT", conn->OutputQueueLength - conn->OutputGetPointer);
|
|
}
|
|
}
|
|
}
|
|
SendDlgItemMessage(MainWnd,100,LB_ADDSTRING,0,(LPARAM)msg);
|
|
}
|
|
|
|
SetDlgItemInt(hWnd, IDC_MSGS, NumberofMessages, FALSE);
|
|
|
|
n = 0;
|
|
|
|
|
|
SetDlgItemInt(hWnd, IDC_SYSOPMSGS, SYSOPMsgs, FALSE);
|
|
SetDlgItemInt(hWnd, IDC_HELD, HeldMsgs, FALSE);
|
|
SetDlgItemInt(hWnd, IDC_SMTP, SMTPMsgs, FALSE);
|
|
|
|
SetDlgItemInt(hWnd, IDC_CHATSEM, ChatSemaphore.Clashes, FALSE);
|
|
|
|
now = time(NULL);
|
|
|
|
tm = gmtime(&now);
|
|
sprintf_s(tim, sizeof(tim), "%02d:%02d", tm->tm_hour, tm->tm_min);
|
|
SetDlgItemText(hWnd, IDC_UTC, tim);
|
|
|
|
tm = localtime(&now);
|
|
sprintf_s(tim, sizeof(tim), "%02d:%02d", tm->tm_hour, tm->tm_min);
|
|
SetDlgItemText(hWnd, IDC_LOCAL, tim);
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define MAX_PENDING_CONNECTS 4
|
|
|
|
#define VERSION_MAJOR 2
|
|
#define VERSION_MINOR 0
|
|
|
|
SOCKADDR_IN local_sin; /* Local socket - internet style */
|
|
|
|
PSOCKADDR_IN psin;
|
|
|
|
SOCKET sock;
|
|
|
|
|
|
BOOL GetConfigFromRegistry()
|
|
{
|
|
ChatApplNum = regGetIntValue("ApplNum", 0);
|
|
MaxChatStreams = regGetIntValue("MaxStreams", 0);
|
|
|
|
regGetStringValue("MapPosition", Position, 80);
|
|
regGetStringValue("MapPopup", PopupText, 250);
|
|
PopupMode = regGetIntValue("PopupMode", 0);
|
|
|
|
regGetStringValue("ConsoleSize", ConsoleSize, 32);
|
|
regGetStringValue("MonitorSize", MonitorSize, 32);
|
|
regGetStringValue("DebugSize", DebugSize, 32);
|
|
regGetStringValue("WindowSize", WindowSize, 32);
|
|
regGetStringValue("Version", Version, 32 );
|
|
Bells = regGetIntValue("Bells", 0);
|
|
FlashOnBell = regGetIntValue("FlashOnBell", 0);
|
|
StripLF = regGetIntValue("StripLF", 0);
|
|
WarnWrap = regGetIntValue("WarnWrap", 0);
|
|
WrapInput = regGetIntValue("WrapInput", 0);
|
|
FlashOnConnect = regGetIntValue("FlashOnConnect", 0);
|
|
CloseWindowOnBye = regGetIntValue("CloseWindowOnBye", 0);
|
|
|
|
return regGetStringValue("OtherChatNodes", OtherNodesList, 999); // Return false if not there
|
|
}
|
|
|
|
|
|
BOOL Initialise()
|
|
{
|
|
int i;
|
|
ChatCIRCUIT * conn;
|
|
HMODULE ExtDriver = LoadLibrary("bpq32.dll");
|
|
|
|
// Register message for posting by BPQDLL
|
|
|
|
CheckTimer(); // Make sure init is complete
|
|
|
|
BPQMsg = RegisterWindowMessage(BPQWinMsg);
|
|
|
|
Retry:
|
|
|
|
if (ChatApplNum)
|
|
{
|
|
char * ptr1 = GetApplCall(ChatApplNum);
|
|
char * Save;
|
|
|
|
if (*ptr1 > 0x20)
|
|
{
|
|
char * Context;
|
|
|
|
memcpy(OurNode, ptr1, 10);
|
|
strlop(OurNode, ' ');
|
|
strcpy(ChatSYSOPCall, OurNode);
|
|
strlop(ChatSYSOPCall, '-');
|
|
|
|
ptr1=GetApplAlias(ChatApplNum);
|
|
memcpy(OurAlias, ptr1,10);
|
|
strlop(OurAlias, ' ');
|
|
|
|
ChatApplMask = 1<<(ChatApplNum-1);
|
|
|
|
// Set up other nodes list. rtlink messes with the string so pass copy
|
|
|
|
// New format can have connect scrips and separates lines with crlf, not space
|
|
|
|
|
|
if (strchr(OtherNodesList, '\r')) // Has connect script entries
|
|
{
|
|
Save = ptr1 = strtok_s(_strdup(OtherNodesList), "\r\n", &Context);
|
|
|
|
while (ptr1 && ptr1[0])
|
|
{
|
|
rtlink(ptr1);
|
|
ptr1 = strtok_s(NULL, "\r\n", &Context);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Save = ptr1 = strtok_s(_strdup(OtherNodesList), " ,\r", &Context);
|
|
|
|
while (ptr1)
|
|
{
|
|
rtlink(ptr1);
|
|
ptr1 = strtok_s(NULL, " ,\r", &Context);
|
|
}
|
|
}
|
|
free(Save);
|
|
SetupChat();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DialogBox(hInst, MAKEINTRESOURCE(CHAT_CONFIG), hWnd, ConfigWndProc);
|
|
goto Retry;
|
|
}
|
|
|
|
// Allocate Streams
|
|
|
|
for (i=0; i < MaxChatStreams; i++)
|
|
{
|
|
conn = &ChatConnections[i];
|
|
conn->BPQStream = FindFreeStream();
|
|
|
|
if (conn->BPQStream == 255) break;
|
|
|
|
NumberofChatStreams++;
|
|
|
|
BPQSetHandle(conn->BPQStream, hWnd);
|
|
|
|
SetAppl(conn->BPQStream, 3, ChatApplMask);
|
|
Disconnect(conn->BPQStream);
|
|
}
|
|
|
|
|
|
if (cfgMinToTray)
|
|
{
|
|
char Text[80];
|
|
wsprintf(Text, "Chat Server %s ", Session);
|
|
AddTrayMenuItem(MainWnd, Text);
|
|
}
|
|
|
|
SetTimer(hWnd,1,10000,NULL); // Slow Timer (10 Secs)
|
|
SetTimer(hWnd,2,100,NULL); // Send to Node (100 ms)
|
|
|
|
CheckMenuItem(hMenu,IDM_LOGCHAT, (LogCHAT) ? MF_CHECKED : MF_UNCHECKED);
|
|
|
|
sprintf(ChatSignoffMsg, "73 de %s\r", ChatSYSOPCall);
|
|
|
|
if (ChatWelcomeMsg[0] == 0)
|
|
strcpy(ChatWelcomeMsg, "G8BPQ Chat Server.$WType /h for command summary.$WBringing up links to other nodes.$W"
|
|
"This may take a minute or two.$WThe /p command shows what nodes are linked.$W");
|
|
|
|
RefreshMainWindow();
|
|
|
|
DeleteLogFiles();
|
|
|
|
CreateChatPipeThread();
|
|
|
|
|
|
if (ExtDriver)
|
|
pRunEventProgram = GetProcAddress(ExtDriver,"_RunEventProgram@8");
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int CriticalErrorHandler(char * error)
|
|
{
|
|
Debugprintf("Critical Error %s", error);
|
|
ProgramErrors = 25;
|
|
CheckProgramErrors(); // Force close
|
|
return 0;
|
|
}
|
|
|
|
|
|
VOID SaveWindowConfig()
|
|
{
|
|
wsprintf(MonitorSize,"%d,%d,%d,%d",MonitorRect.left,MonitorRect.right,MonitorRect.top,MonitorRect.bottom);
|
|
wsprintf(DebugSize,"%d,%d,%d,%d",DebugRect.left,DebugRect.right,DebugRect.top,DebugRect.bottom);
|
|
wsprintf(WindowSize,"%d,%d,%d,%d",MainRect.left,MainRect.right,MainRect.top,MainRect.bottom);
|
|
|
|
wsprintf(Version,"%d,%d,%d,%d", Ver[0], Ver[1], Ver[2], Ver[3]);
|
|
|
|
if (ConsoleRect.right)
|
|
wsprintf(ConsoleSize,"%d,%d,%d,%d",ConsoleRect.left, ConsoleRect.right, ConsoleRect.top, ConsoleRect.bottom);
|
|
|
|
return;
|
|
}
|
|
|
|
char InfoBoxText[100];
|
|
|
|
|
|
INT_PTR CALLBACK InfoDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int Command;
|
|
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
|
|
switch (message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
|
|
SetDlgItemText(hDlg, 5050, InfoBoxText);
|
|
|
|
return (INT_PTR)TRUE;
|
|
|
|
case WM_COMMAND:
|
|
|
|
Command = LOWORD(wParam);
|
|
|
|
switch (Command)
|
|
{
|
|
case 0:
|
|
case IDCANCEL:
|
|
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
return (INT_PTR)TRUE;
|
|
|
|
}
|
|
break;
|
|
}
|
|
|
|
return (INT_PTR)FALSE;
|
|
}
|
|
|
|
|
|
int GetMultiLineDialog(HWND hDialog, int DLGItem)
|
|
{
|
|
char Text[10000];
|
|
|
|
GetDlgItemText(hDialog, DLGItem, Text, 10000);
|
|
|
|
// We can now have connect scripts for each node, so leave cr/lf
|
|
|
|
if (Text[strlen(Text)-1] != '\n') // no terminating crlf?
|
|
strcat(Text, "\r\n");
|
|
|
|
strcpy(OtherNodesList, Text);
|
|
return TRUE;
|
|
}
|
|
|
|
INT_PTR CALLBACK ConfigWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int Command;
|
|
char Text[10000] = "";
|
|
char * ptr1, *ptr2, *Context;
|
|
|
|
switch (message)
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
if (strchr(OtherNodesList, 13)) // New format with connect scripts?
|
|
{
|
|
strcpy(Text, OtherNodesList);
|
|
/*
|
|
ptr2 = ptr1 = strtok_s(_strdup(OtherNodesList), "\r", &Context);
|
|
|
|
while (ptr1 && ptr1[0])
|
|
{
|
|
strcat(Text, ptr1);
|
|
strcat(Text, "\r\n");
|
|
ptr1 = strtok_s(NULL, "\r", &Context);
|
|
|
|
if (*(ptr1) == 10)
|
|
ptr1++;
|
|
}
|
|
*/
|
|
}
|
|
else
|
|
{
|
|
ptr2 = ptr1 = strtok_s(_strdup(OtherNodesList), " ,\r", &Context);
|
|
|
|
while (ptr1)
|
|
{
|
|
strcat(Text, ptr1);
|
|
strcat(Text, "\r\n");
|
|
ptr1 = strtok_s(NULL, " ,\r", &Context);
|
|
}
|
|
free(ptr2);
|
|
}
|
|
SetDlgItemInt(hDlg, ID_CHATAPPL, ChatApplNum, FALSE);
|
|
SetDlgItemInt(hDlg, ID_STREAMS, MaxChatStreams, FALSE);
|
|
SetDlgItemText(hDlg, ID_CHATNODES, Text);
|
|
|
|
// Replace $W in Welcome Message with cr lf
|
|
|
|
ptr2 = ptr1 = _strdup(ChatWelcomeMsg);
|
|
|
|
scan:
|
|
|
|
ptr1 = strstr(ptr1, "$W");
|
|
|
|
if (ptr1)
|
|
{
|
|
*(ptr1++)=13; // put in cr
|
|
*(ptr1++)=10; // put in lf
|
|
|
|
goto scan;
|
|
}
|
|
|
|
SetDlgItemText(hDlg, IDM_CHATUSERMSG, ptr2);
|
|
|
|
free(ptr2);
|
|
|
|
return (INT_PTR)TRUE;
|
|
|
|
case WM_CTLCOLORDLG:
|
|
|
|
return (LONG)bgBrush;
|
|
|
|
case WM_CTLCOLORSTATIC:
|
|
{
|
|
HDC hdcStatic = (HDC)wParam;
|
|
SetTextColor(hdcStatic, RGB(0, 0, 0));
|
|
SetBkMode(hdcStatic, TRANSPARENT);
|
|
return (LONG)bgBrush;
|
|
}
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
Command = LOWORD(wParam);
|
|
|
|
if (Command == 2002)
|
|
return TRUE;
|
|
|
|
switch (Command)
|
|
{
|
|
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
return (INT_PTR)TRUE;
|
|
|
|
case SAVEWELCOME:
|
|
|
|
GetDlgItemText(hDlg, IDM_CHATUSERMSG, ChatWelcomeMsg, 999);
|
|
|
|
// Replace cr lf in string with $W
|
|
|
|
ptr1 = ChatWelcomeMsg;
|
|
|
|
scan2:
|
|
|
|
ptr1 = strstr(ptr1, "\r\n");
|
|
|
|
if (ptr1)
|
|
{
|
|
*(ptr1++)='$'; // put in cr
|
|
*(ptr1++)='W'; // put in lf
|
|
|
|
goto scan2;
|
|
}
|
|
|
|
SaveChatConfigFile(ChatConfigName);
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
return (INT_PTR)TRUE;
|
|
|
|
case SAVENODES:
|
|
|
|
SaveChatConfig(hDlg);
|
|
EndDialog(hDlg, LOWORD(wParam));
|
|
return (INT_PTR)TRUE;
|
|
}
|
|
break;
|
|
|
|
}
|
|
return (INT_PTR)FALSE;
|
|
}
|
|
|
|
|
|
|