diff --git a/.gitignore b/.gitignore index 14065f4..06196a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ *.ncb *.suo +*.bsc *.user .svn/* +.vs/* \ No newline at end of file diff --git a/BPQChat.rc b/BPQChat.rc index dc873e2..e3b82f8 100644 --- a/BPQChat.rc +++ b/BPQChat.rc @@ -12,7 +12,7 @@ #undef APSTUDIO_HIDDEN_SYMBOLS #define CHAT #define IDC_STATIC -1 -#include "..\CommonSource\Versions.h" +#include "Versions.h" ///////////////////////////////////////////////////////////////////////////// diff --git a/BPQChat.vcxproj b/BPQChat.vcxproj new file mode 100644 index 0000000..c776b12 --- /dev/null +++ b/BPQChat.vcxproj @@ -0,0 +1,168 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + 18.0 + {2BDD2C8A-2B4A-496C-A2EA-6B49AA0670B1} + BPQChat + Win32Proj + + + + Application + v145 + NotSet + true + + + Application + v145 + NotSet + + + + + + + + + + + + + <_ProjectFileVersion>18.0.12106.202 + + + C:\Dev\Msdev2005\$(SolutionName)\$(ProjectName)\$(Configuration)\ + C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(ProjectName)\$(Configuration)\ + true + + + C:\Dev\Msdev2005\$(SolutionName)\$(ProjectName)\$(Configuration)\ + C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(ProjectName)\$(Configuration)\ + false + + + + + + + Disabled + Win32bits;..\BPQSource;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USE_32BIT_TIME_T;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + true + + Level3 + EditAndContinue + CompileAsC + + + Win32bits\bpq32.lib;wsock32.lib;comctl32.lib;winmm.lib;Win32bits\libconfig.lib;DbgHelp.lib;%(AdditionalDependencies) + c:\DevProgs\bpq32\BPQChat.exe + true + $(IntDir)$(TargetName).pdb + true + $(IntDir)BBSListings\BPQChat.map + true + Windows + MachineX86 + + + + + + + + + + + MaxSpeed + false + Win32bits;..\BPQSource;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USE_32BIT_TIME_T;%(PreprocessorDefinitions) + MultiThreaded + + All + $(IntDir)BBSListings\ + Level3 + + CompileAsC + + + Win32bits\bpq32.lib;wsock32.lib;comctl32.lib;Win32bits\libconfig.lib;DbgHelp.lib;%(AdditionalDependencies) + c:\DevProgs\bpq32\BPQChat.exe + false + $(IntDir)$(TargetName).pdb + true + $(IntDir)BBSListings\BPQChat.map + Windows + true + true + + MachineX86 + + + + + $(IntDir) + + + $(IntDir) + + + $(IntDir) + + + $(IntDir) + $(IntDir) + $(IntDir) + $(IntDir) + $(IntDir)%(Filename)1.xdc + + + $(IntDir) + $(IntDir) + $(IntDir) + $(IntDir) + $(IntDir)%(Filename)1.xdc + + + $(IntDir) + + + $(IntDir) + $(IntDir) + $(IntDir) + $(IntDir) + $(IntDir) + + + $(IntDir) + + + $(IntDir) + $(IntDir) + $(IntDir) + $(IntDir) + $(IntDir) + + + + + + + + + \ No newline at end of file diff --git a/BPQMail.c b/BPQMail.c index 62c2ff9..5300836 100644 --- a/BPQMail.c +++ b/BPQMail.c @@ -1168,6 +1168,7 @@ // Allow lower case SMTP/POP3 commands (39) // Fix Webmail Send Reply with SMTP server messages (39) // Fix paging in PG server (39) +// Fix crash in Webmail display message if message doesn't exist or isn't for you (41) #include "bpqmail.h" diff --git a/BPQMail.rc b/BPQMail.rc index 88d1116..26e48ab 100644 --- a/BPQMail.rc +++ b/BPQMail.rc @@ -16,7 +16,7 @@ #include "AFXRES.h" #undef APSTUDIO_HIDDEN_SYMBOLS #define MAILCHAT -#include "..\CommonSource\Versions.h" +#include "Versions.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS diff --git a/BPQMail.vcxproj b/BPQMail.vcxproj new file mode 100644 index 0000000..c3f3a7d --- /dev/null +++ b/BPQMail.vcxproj @@ -0,0 +1,208 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + 18.0 + {3766AA10-C777-4ED8-A83D-F1452DE9B665} + TelnetServer + Win32Proj + + + + Application + v145 + NotSet + true + + + Application + v145 + false + NotSet + + + + + + + + + + + + + <_ProjectFileVersion>18.0.12106.202 + + + C:\Dev\Msdev2005\$(SolutionName)\$(ProjectName)\$(Configuration)\ + C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(ProjectName)\$(Configuration)\ + true + + + C:\Dev\Msdev2005\$(SolutionName)\$(ProjectName)\$(Configuration)\ + C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(ProjectName)\$(Configuration)\ + false + + + + + + + Disabled + ..\BPQSource\Win32bits;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USE_32BIT_TIME_T;NOMQTT;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + true + + Level3 + EditAndContinue + CompileAsC + + + ..\Include;%(AdditionalIncludeDirectories) + + + Win32bits\bpq32.lib;wsock32.lib;comctl32.lib;winmm.lib;Win32bits\libconfig.lib;DbgHelp.lib;%(AdditionalDependencies) + c:\DevProgs\bpq32\BPQMail.exe + false + LIBCMT;%(IgnoreSpecificDefaultLibraries) + true + $(IntDir)$(TargetName).pdb + true + $(IntDir)BBSListings\bpqmail.map + true + Windows + MachineX86 + + + + + + + + + + + MaxSpeed + false + Win32bits;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USE_32BIT_TIME_T;NOMQTT;%(PreprocessorDefinitions) + MultiThreaded + + Level3 + ProgramDatabase + CompileAsC + + + ..\Include;%(AdditionalIncludeDirectories) + + + Win32bits\bpq32.lib;wsock32.lib;comctl32.lib;winmm.lib;Win32bits\libconfig.lib;DbgHelp.lib;%(AdditionalDependencies) + c:\DevProgs\bpq32\BPQMail.exe + true + c:\DevProgs\bpq32\BPQMail.pdb + true + c:\DevProgs\bpq32\BPQMail.map + Windows + true + true + + MachineX86 + + + + + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + All + $(IntDir) + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + + + + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + + + + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + All + $(IntDir) + $(IntDir) + $(IntDir)%(Filename)1.xdc + + + + + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + + + + + + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + + + + + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + $(IntDir)%(Filename)1.obj + $(IntDir)%(Filename)1.xdc + + + + + + + + + + + + + \ No newline at end of file diff --git a/BPQNRR.c b/BPQNRR.c index 97e2b45..2bcab5c 100644 --- a/BPQNRR.c +++ b/BPQNRR.c @@ -214,3 +214,4 @@ VOID SendNRRecordRoute(struct DEST_LIST * DEST, TRANSPORTENTRY * Session) C_Q_ADD(&DEST->DEST_Q, Msg); } + diff --git a/BPQTermTCP.h b/BPQTermTCP.h new file mode 100644 index 0000000..d230864 --- /dev/null +++ b/BPQTermTCP.h @@ -0,0 +1,90 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by BPQTermTCP.rc +// +#define IDR_MENU1 101 +#define BPQMENU 101 +#define BPQDISCONNECT 103 +#define IDD_CONFIG 104 +#define IDD_FONT 105 +#define IDD_ALERTDLG 106 +#define IDD_LISTEN 107 + +#define MONITOR_ADDPORT 400 +#define IDC_HOST 1004 +#define IDC_PORT 1005 +#define IDC_USER 1006 +#define IDC_PASS 1007 +#define IDC_FONTWIDTH 1008 +#define IDC_FONTNAME 1009 +#define IDC_CODEPAGE 1010 +#define IDC_CHARSET 1011 +#define IDC_FONTSIZE 1012 +#define IDC_AUTO 1013 +#define IDC_1251 1014 +#define IDC_1252 1015 +#define IDC_437 1016 +#define IDC_UTF8 1017 +#define IDC_Send1251 1018 +#define IDC_Send1252 1019 +#define IDC_ALERTINTERVAL 1020 +#define IDC_RADIO1 1021 +#define IDC_RADIO2 1022 +#define IDC_ALERTFILENAME 1023 +#define IDC_PLAYFILENAME 1023 +#define IDC_FREQ 1024 +#define IDC_DURATION 1025 +#define IDC_USEKEYWORDS 1026 +#define IDC_ALERTKEYNAME 1027 +#define IDC_LISTENPORT 1028 + +#define BPQMTX 1164 +#define BPQMCOM 1165 +#define BPQCOPYMON 1166 +#define BPQCOPYOUT 1167 +#define BPQCLEARMON 1168 +#define BPQCLEAROUT 1169 +#define BPQBELLS 1170 +#define BPQCHAT 1171 +#define BPQHELP 1172 +#define BPQStripLF 1173 +#define BPQLogOutput 1174 +#define BPQLogMonitor 1175 +#define BPQSendDisconnected 1176 +#define BPQMNODES 1177 +#define MONCOLOUR 1178 +#define CHATTERM 1179 +#define MUIONLY 1180 +#define BPQPORT 1181 +#define BPQENABLE 1182 +#define YAPPSEND 1200 +#define YAPPDIR 1201 +#define BPQAUTOCONNECT 40001 +#define BPQAPPL1 40002 +#define BPQAPPL2 40003 +#define BPQAPPL3 40004 +#define BPQAPPL4 40005 +#define BPQAPPL6 40006 +#define BPQAPPL7 40007 +#define BPQAPPL8 40008 +#define BPQAPPL5 40009 +#define BPQFLAGS1 40010 +#define BPQFLAGS2 40011 +#define BPQFLAGS3 40012 +#define BPQFLAGS4 40013 +#define ID_SETUP_FONT 40025 +#define ID_SETUP_ALERTSETUP 40026 +#define BPQCONNECT1 40101 +#define IDC_HOST1 40201 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 107 +#define _APS_NEXT_COMMAND_VALUE 40027 +#define _APS_NEXT_CONTROL_VALUE 1027 +#define _APS_NEXT_SYMED_VALUE 104 +#endif +#endif diff --git a/BPQTermTCP.ini b/BPQTermTCP.ini new file mode 100644 index 0000000..3fe4d61 --- /dev/null +++ b/BPQTermTCP.ini @@ -0,0 +1,20 @@ +[Session 1] +PortMask=0 +Bells=0 +StripLF=0 +MTX=1 +MCOM=1 +MUIONLY=0 +Split=50 +MONColour=0 +MonNODES=1 +MonPorts=0 +ChatMode=0 +CurrentHost=0 +Size=34,650,47,669 +FontName=Courier New +CharSet=0 +CodePage=437 +FontSize=20 +FontWidth=8 +AlertInterval=3600 diff --git a/BPQTermTCP.rc b/BPQTermTCP.rc new file mode 100644 index 0000000..c44d16a --- /dev/null +++ b/BPQTermTCP.rc @@ -0,0 +1,336 @@ +//Microsoft Developer Studio generated resource script. +// +#define TermTCP +#include "bpqtermTCP.h" + + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "afxres.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +#include "winver.h" +#define BPQBASE 1100 + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ALERTDLG DIALOG DISCARDABLE 0, 0, 250, 121 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Alert Settings" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,62,100,50,14 + PUSHBUTTON "Cancel",IDCANCEL,137,100,50,14 + LTEXT "Alert After Interval",IDC_STATIC,7,9,65,9, + SS_CENTERIMAGE + EDITTEXT IDC_ALERTINTERVAL,83,8,29,13,ES_AUTOHSCROLL + CONTROL "Beep",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,7,27,33,15 + CONTROL "Play File",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,7,50, + 52,14 + EDITTEXT IDC_ALERTFILENAME,83,49,151,15,ES_AUTOHSCROLL + LTEXT "Freq",IDC_STATIC,47,30,15,8 + LTEXT "Duration",IDC_STATIC,120,30,28,8 + EDITTEXT IDC_FREQ,83,28,29,13,ES_AUTOHSCROLL + EDITTEXT IDC_DURATION,154,28,29,13,ES_AUTOHSCROLL + CONTROL "Use Keyword File",IDC_USEKEYWORDS,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,73,71,10 + EDITTEXT IDC_ALERTKEYNAME,83,72,151,15,ES_AUTOHSCROLL +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_ALERTDLG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 243 + TOPMARGIN, 7 + BOTTOMMARGIN, 114 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.K.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +BPQMAINWINDOW DIALOG DISCARDABLE 17, 25, 300, 300 +STYLE DS_3DLOOK | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | + WS_THICKFRAME +CAPTION "BPQTerminal Version 1.0.0" +MENU MENU_1 +CLASS "BPQMAINWINDOW" +FONT 8, "FixedSys" +BEGIN + LISTBOX 116,5,6,290,134,LBS_MULTIPLESEL | LBS_OWNERDRAWFIXED | + LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | + WS_HSCROLL + EDITTEXT 118,5,280,440,15,ES_AUTOHSCROLL | ES_NOHIDESEL + CTEXT "",119,0,145,300,5,SS_NOTIFY +END + +IDD_CONFIG DIALOG DISCARDABLE 0, 0, 181, 129 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "TCP Host Config" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Host",IDC_STATIC,7,15,24,9 + EDITTEXT IDC_HOST,46,13,114,12,ES_AUTOHSCROLL + LTEXT "Port",IDC_STATIC,7,32,24,9 + EDITTEXT IDC_PORT,46,30,53,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "User",IDC_STATIC,7,49,24,9 + EDITTEXT IDC_USER,46,47,89,12,ES_AUTOHSCROLL + LTEXT "Password",IDC_STATIC,7,66,39,9 + EDITTEXT IDC_PASS,46,64,90,12,ES_AUTOHSCROLL + DEFPUSHBUTTON "Save",IDOK,33,91,50,14 + PUSHBUTTON "Cancel",IDCANCEL,95,91,50,14 +END + +IDD_LISTEN DIALOG DISCARDABLE 0, 0, 181, 129 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "TCP Listen Config" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Port",IDC_STATIC,7,32,24,9 + EDITTEXT IDC_LISTENPORT,46,30,53,12,ES_AUTOHSCROLL | ES_NUMBER + DEFPUSHBUTTON "Save",IDOK,33,91,50,14 + PUSHBUTTON "Cancel",IDCANCEL,95,91,50,14 +END + + +IDD_FONT DIALOG DISCARDABLE 0, 0, 187, 206 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Font Setup" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Save",IDOK,39,182,50,14 + PUSHBUTTON "Cancel",IDCANCEL,92,182,50,14 + LTEXT "Font Width",IDC_STATIC,7,166,41,9 + EDITTEXT IDC_FONTWIDTH,53,164,39,12,ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_FONTSIZE,53,149,38,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Font Size",IDC_STATIC,7,151,44,9 + LTEXT "Interpret non-UTF8 input as",IDC_STATIC,7,10,96,11 + CONTROL "Auto",IDC_AUTO,"Button",BS_AUTORADIOBUTTON,15,25,31,10 + CONTROL "CP1251 (Cyrillic)",IDC_1251,"Button",BS_AUTORADIOBUTTON, + 15,40,67,10 + CONTROL "CP1252 (Western Europe)",IDC_1252,"Button", + BS_AUTORADIOBUTTON,15,55,99,10 + CONTROL "CP437 (Windows Line Draw)",IDC_437,"Button", + BS_AUTORADIOBUTTON,15,70,107,10 + LTEXT "Send as",IDC_STATIC,7,85,27,8 + CONTROL "UTF8",IDC_UTF8,"Button",BS_AUTORADIOBUTTON | WS_GROUP, + 15,100,34,10 + CONTROL "CP1251",IDC_Send1251,"Button",BS_AUTORADIOBUTTON,15,115, + 41,10 + CONTROL "CP1252",IDC_Send1252,"Button",BS_AUTORADIOBUTTON,15,130, + 41,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_CONFIG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 174 + TOPMARGIN, 6 + BOTTOMMARGIN, 122 + END + + IDD_FONT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 180 + TOPMARGIN, 7 + BOTTOMMARGIN, 199 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "bpqtermTCP.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""..\\cinclude\\afxres.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""winver.h""\r\n" + "#define BPQBASE 1100\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""..\\CommonSource\\Versions.h""\r\n" + "#include ""..\\StdVer.inc""\r\n" + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Cursor +// + +IDC_DRAGSIZE CURSOR DISCARDABLE "DragSize.cur" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +MENU_1 MENU DISCARDABLE +BEGIN + POPUP "Connect" + BEGIN + MENUITEM "Host 1", BPQCONNECT1 + MENUITEM "Host 2", 40102 + MENUITEM "Host 3", 40103 + MENUITEM "Host 4", 40104 + MENUITEM "Host 5", 40105 + MENUITEM "Host 6", 40106 + MENUITEM "Host 7", 40107 + MENUITEM "Host 8", 40108 + MENUITEM "Host 9", 40109 + MENUITEM "Host 10", 40110 + MENUITEM "Host 11", 40111 + MENUITEM "Host 12", 40112 + MENUITEM "Host 13", 40113 + MENUITEM "Host 14", 40114 + MENUITEM "Host 15", 40115 + MENUITEM "Host 16", 40116 + END + MENUITEM "Disconnect", BPQDISCONNECT + + POPUP "Listen" + BEGIN + MENUITEM "Enable", BPQENABLE + MENUITEM "Port", BPQPORT + END + + POPUP "Setup" + BEGIN + POPUP "TCP Hosts" + BEGIN + MENUITEM "Host 1", IDC_HOST1 + MENUITEM "Host 2", 40202 + MENUITEM "Host 3", 40203 + MENUITEM "Host 4", 40204 + MENUITEM "Host 5", 40205 + MENUITEM "Host 6", 40206 + MENUITEM "Host 7", 40207 + MENUITEM "Host 8", 40208 + MENUITEM "Host 9", 40209 + MENUITEM "Host 10", 40210 + MENUITEM "Host 11", 40211 + MENUITEM "Host 12", 40212 + MENUITEM "Host 13", 40213 + MENUITEM "Host 14", 40214 + MENUITEM "Host 15", 40215 + MENUITEM "Host 16", 40216 + END + MENUITEM "Font Setup", ID_SETUP_FONT + MENUITEM "Enable Bells", BPQBELLS + MENUITEM "Strip Linefeeds", BPQStripLF + MENUITEM "Log Monitor", BPQLogMonitor + MENUITEM "Log Output", BPQLogOutput + MENUITEM "Chat Terminal Mode", CHATTERM + MENUITEM "Alert Setup", ID_SETUP_ALERTSETUP + END + POPUP "Monitor" + BEGIN + MENUITEM "Monitor TX", BPQMTX + MENUITEM "Monitor Supervisory", BPQMCOM + MENUITEM "Only monitor UI frames", MUIONLY + MENUITEM "Monitor NODES", BPQMNODES + MENUITEM "Enable Colour", MONCOLOUR + MENUITEM "Add Port", MONITOR_ADDPORT + END + POPUP "Edit" + BEGIN + MENUITEM "Copy Monitor Window", BPQCOPYMON + MENUITEM "Copy Output Window", BPQCOPYOUT + MENUITEM "Clear Monitor Window", BPQCLEARMON + MENUITEM "Clear Output Window", BPQCLEAROUT + END + POPUP "YAPP" + BEGIN + MENUITEM "Send File", YAPPSEND + MENUITEM "Set Receive Directory", YAPPDIR + END +END + +#endif // English (U.K.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "Versions.h" +#include "StdVer.inc" + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/BPQTermTCP.vcproj b/BPQTermTCP.vcproj new file mode 100644 index 0000000..2f8eed3 --- /dev/null +++ b/BPQTermTCP.vcproj @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BPQTermTCP.vcxproj b/BPQTermTCP.vcxproj new file mode 100644 index 0000000..a0fbe10 --- /dev/null +++ b/BPQTermTCP.vcxproj @@ -0,0 +1,107 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + 18.0 + {99625C77-CABA-469A-A5A7-ECB4EE354225} + BPQTermTCP + Win32Proj + 10.0 + + + + Application + v145 + Unicode + + + Application + v145 + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>18.0.12106.202 + + + c:\DevProgs\bpq32\ + C:\Dev\Msdev2005\Intermed\BPQTermTCP\Debug\ + true + + + Release\ + C:\Dev\Msdev2005\Intermed\BPQTermTCP\Release\ + false + + + + Disabled + ./;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + true + + true + Level3 + EditAndContinue + + + ws2_32.lib;winmm.lib;%(AdditionalDependencies) + c:\DevProgs\bpq32\BPQTermTCP.exe + true + Windows + MachineX86 + false + + + + + Full + ./;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreaded + + true + Level3 + ProgramDatabase + + + ws2_32.lib;winmm.lib;%(AdditionalDependencies) + c:\DevProgs\bpq32\BPQTermTCP.exe + true + Windows + true + true + MachineX86 + + + + + + + + + + + + \ No newline at end of file diff --git a/BPQTerminal.c b/BPQTerminal.c new file mode 100644 index 0000000..2b4b3a0 --- /dev/null +++ b/BPQTerminal.c @@ -0,0 +1,2413 @@ + +// Version 2.0.1 November 2007 + +// Change resizing algorithm + + +// Version 2.0.2 January 2008 + +// Restore Checked state of Bells and AutoConnect Flags +// Call CheckTimer on startup (for new Initialisation Scheme for perl) + +// Version 2.0.3 July 2008 + +// Display lines received without a terminaing CR + + +// Version 2.0.4 November 2008 + +// Add option to remove a Line Feed following a CR +// Add Logging Option + +// Version 2.0.5 January 2009 + +// Add Start Minimized Option + +// Version 2.0.6 June 2009 + +// Add Option to send *** Disconnnected on disconnect +// Add line wrap code +// Add option not to monitor NODES broadcasts + +// Version 2.0.7 October 2009 + +// Add input buffer scrollback. +// Fix monitoring when PORTNUM specified + +// Version 2.0.8 December 2009 + +// Fix use of numeric keypad 2 and 8 (were treated as up and down) + +// Version 2.0.9 March 2010 + +// Add colour for monitor and BPQ Chat + +// Version 2.0.0 October 2010 + +// Add Chat Terminal Mode (sends keepalives) + +// Version 2.1.0 August 2011 + +// Add Copy/Paste capability to output window. +// Add Font Selection +// Get Registry Tree from BPQ32.dll +// Add Command to reset Monitor/Output window split + +// Version 2.1.1 October 2011 + +// Wrap overlong lines + +// Version 2.1.2 Jan 2012 + +// Call CloseBPQ32 on exit +// Fix ClearOutputWindow +// Save MonitorNodes flag + +// Version 2.2.1 June 2012 + +// Add UIOnly Monitor Option + +// Version 2.2.2.1 Nov 2014 +// Fix possible crash on processing part line + + +// Version 2.2.3.1 Dec 2014 +// Remove "Enable Chat" option + +// Version 2.2.4.1 Dec 2015 +// Add Port Names to Monitor Config Menu + + +// Add Chat Terminal Mode + +// Version 2.2.5.1 Sep 2019 + +// Recompile for change to Port Struct + +// Version 2.2.5.2 May 2023 +// Changes for compatibility with 63 port BPQ32 + +#define _USE_32BIT_TIME_T +#define _CRT_SECURE_NO_DEPRECATE + +#define pthread_t DWORD +#include "asmstrucs.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "bpqterminal.h" + +#define BPQBASE WM_USER +// +// Port monitoring flags use BPQBASE -> BPQBASE+100 + +#include "bpq32.h" // BPQ32 API Defines +#define BPQTerm +#include "Versions.h" +#include "GetVersion.h" + +#define BGCOLOUR RGB(236,233,216) + +HBRUSH bgBrush; + +UINT BPQMsg; + +HKEY FAR WINAPI GetRegistryKey(); +char * FAR WINAPI GetRegistryKeyText(); + +HKEY REGTREE = HKEY_LOCAL_MACHINE; // Default + +HINSTANCE hInst; +char AppName[] = "BPQTerm 32"; +char ClassName[] = "BPQMAINWINDOW"; +char Title[80]; + +// Foward declarations of functions included in this code module: + +ATOM MyRegisterClass(CONST WNDCLASS*); +BOOL InitApplication(HINSTANCE); +BOOL InitInstance(HINSTANCE, int); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); +int NewLine(); + +int ProcessBuff(char * readbuff,int len); + +int EnableConnectMenu(HWND hWnd); +int EnableDisconnectMenu(HWND hWnd); +int DisableConnectMenu(HWND hWnd); +int DisableDisconnectMenu(HWND hWnd); +int ToggleAutoConnect(HWND hWnd); +int DoReceivedData(HWND hWnd); +int DoStateChange(HWND hWnd); +int CopyScreentoBuffer(char * buff); +int DoMonData(HWND hWnd); +int TogglePort(HWND hWnd, int Item, uint64_t mask); +int ToggleMTX(HWND hWnd); +int ToggleMCOM(HWND hWnd); +int ToggleMUI(HWND hWnd); +int ToggleParam(HWND hWnd, BOOL * Param, int Item); +int ToggleChat(HWND hWnd); +void MoveWindows(); +void CopyListToClipboard(HWND hWnd); +void CopyRichTextToClipboard(HWND hWnd); +BOOL OpenMonitorLogfile(); +void WriteMonitorLine(char * Msg, int MsgLen); +VOID WritetoOutputWindow(struct RTFTerm * OPData, char * Msg, int len); +VOID DoRefresh(struct RTFTerm * OPData); +INT_PTR CALLBACK FontConfigWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +COLORREF Colours[256] = {0, + RGB(0,0,0), RGB(0,0,128), RGB(0,0,192), RGB(0,0,255), // 1 - 4 + RGB(0,64,0), RGB(0,64,128), RGB(0,64,192), RGB(0,64,255), // 5 - 8 + RGB(0,128,0), RGB(0,128,128), RGB(0,128,192), RGB(0,128,255), // 9 - 12 + RGB(0,192,0), RGB(0,192,128), RGB(0,192,192), RGB(0,192,255), // 13 - 16 + RGB(0,255,0), RGB(0,255,128), RGB(0,255,192), RGB(0,255,255), // 17 - 20 + + RGB(64,0,0), RGB(64,0,128), RGB(64,0,192), RGB(0,0,255), // 21 + RGB(64,64,0), RGB(64,64,128), RGB(64,64,192), RGB(64,64,255), + RGB(64,128,0), RGB(64,128,128), RGB(64,128,192), RGB(64,128,255), + RGB(64,192,0), RGB(64,192,128), RGB(64,192,192), RGB(64,192,255), + RGB(64,255,0), RGB(64,255,128), RGB(64,255,192), RGB(64,255,255), + + RGB(128,0,0), RGB(128,0,128), RGB(128,0,192), RGB(128,0,255), // 41 + RGB(128,64,0), RGB(128,64,128), RGB(128,64,192), RGB(128,64,255), + RGB(128,128,0), RGB(128,128,128), RGB(128,128,192), RGB(128,128,255), + RGB(128,192,0), RGB(128,192,128), RGB(128,192,192), RGB(128,192,255), + RGB(128,255,0), RGB(128,255,128), RGB(128,255,192), RGB(128,255,255), + + RGB(192,0,0), RGB(192,0,128), RGB(192,0,192), RGB(192,0,255), // 61 + RGB(192,64,0), RGB(192,64,128), RGB(192,64,192), RGB(192,64,255), + RGB(192,128,0), RGB(192,128,128), RGB(192,128,192), RGB(192,128,255), + RGB(192,192,0), RGB(192,192,128), RGB(192,192,192), RGB(192,192,255), + RGB(192,255,0), RGB(192,255,128), RGB(192,255,192), RGB(192,2552,255), + + RGB(255,0,0), RGB(255,0,128), RGB(255,0,192), RGB(255,0,255), // 81 + RGB(255,64,0), RGB(255,64,128), RGB(255,64,192), RGB(255,64,255), + RGB(255,128,0), RGB(255,128,128), RGB(255,128,192), RGB(255,128,255), + RGB(255,192,0), RGB(255,192,128), RGB(255,192,192), RGB(255,192,255), + RGB(255,255,0), RGB(255,255,128), RGB(255,255,192), RGB(255,2552,255) +}; + + + +LRESULT APIENTRY InputProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ; +LRESULT APIENTRY MonProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ; +LRESULT APIENTRY SplitProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ; + + +WNDPROC wpOrigInputProc; +WNDPROC wpOrigMonProc; +WNDPROC wpOrigSplitProc; + +HWND hwndInput; +HWND hwndOutput; +HWND hwndMon; +HWND hwndSplit; + +HMENU trayMenu; + +int xsize,ysize; // Screen size at startup + +double Split=0.5; +int SplitPos=300; +#define SplitBarHeight 5 +#define InputBoxHeight 25 +RECT Rect; +RECT MonRect; +RECT OutputRect; +RECT SplitRect; + +int OutputBoxHeight; + +int Height, Width, LastY; + +int maxlinelen = 80; +int CharWidth = 8; + +int ClientHeight, ClientWidth; + + +#define MAXLINES 1000 +#define LINELEN 200 + +char RTFHeader[4000]; + +int RTFHddrLen; + +typedef struct RTFTerm +{ + int CurrentLine; // Line we are writing to in circular buffer. + + int Index; + BOOL SendHeader; + BOOL Finished; + + char OutputScreen[MAXLINES][LINELEN]; + + int Colourvalue[MAXLINES]; + int LineLen[MAXLINES]; + int CharWidth; + int CurrentColour; + int Thumb; + int FirstTime; + int RTFHeight; // Height of RTF control in pixels + BOOL Scrolled; // Window is scrolled back + +}; + +char FontName[100] = "FixedSys"; +int FontSize = 20; +int FontWidth = 8; +int CodePage = 437; +int CharSet = 0; + + +struct RTFTerm OutputData; + +int CurrentHost = 0; +int CfgNo = 0; + +SOCKET sock; + +BOOL MonData = FALSE; + +char Key[80]; +uint64_t portmask=0; +int mtxparam=1; +int mcomparam=1; +int monUI = 0; + +char kbbuf[160]; +int kbptr=0; +char readbuff[100000]; // for stupid bbs programs + +int ptr=0; + +int Stream; +int len,count; + +char callsign[10]; +int state; +int change; +int applmask = 0; +int applflags = 2; // Message to Application +int Sessno = 0; + +int PartLinePtr=0; +int PartLineIndex=0; // Listbox index of (last) incomplete line + +BOOL Bells = FALSE; +BOOL StripLF = FALSE; +BOOL LogMonitor = FALSE; +BOOL LogOutput = FALSE; +BOOL SendDisconnected = TRUE; +BOOL MonitorNODES = TRUE; +BOOL MonitorColour = TRUE; +BOOL ChatMode = FALSE; + +HANDLE MonHandle=INVALID_HANDLE_VALUE; + +HCURSOR DragCursor; +HCURSOR Cursor; + +CONNECTED=FALSE; +AUTOCONNECT=TRUE; + +LOGFONT LFTTYFONT ; + +HFONT hFont ; + +BOOL MinimizetoTray=FALSE; +//BOOL StartMinimized = FALSE; + +HWND MainWnd, hWnd; + +VOID CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime ); + +TIMERPROC lpTimerFunc = (TIMERPROC) TimerProc; + +int TimerHandle = 0; + +int SlowTimer; + +BOOL WINE; + +VOID __cdecl Debugprintf(const char * format, ...) +{ + char Mess[1000]; + va_list(arglist);int Len; + + va_start(arglist, format); + Len = vsprintf_s(Mess, sizeof(Mess), format, arglist); + strcat(Mess, "\r\n"); + OutputDebugString(Mess); + return; +} + + +VOID CALLBACK TimerProc( + + HWND hwnd, // handle of window for timer messages + UINT uMsg, // WM_TIMER message + UINT idEvent, // timer identifier + DWORD dwTime) // current system time +{ + // entered every 10 secs + + CheckTimer(); + + if (!CONNECTED) + return; + + if (!ChatMode) + return; + + SlowTimer++; + + if (SlowTimer > 50) // About 9 mins + { + SlowTimer = 0; + SendMsg(Stream, "\0", 1); + } +} + +// +// FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int) +// +// PURPOSE: Entry point for the application. +// +// COMMENTS: +// +// This function initializes the application and processes the +// message loop. +// +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + MSG msg; + int retCode, disp; + HKEY hKey=0; + char Size[80]; + +/* PCHAR p1, p2, p3; + + p1 = strtok(lpCmdLine, " ,\t\n\r"); + p2 = strtok(NULL, " ,\t\n\r"); + p3 = strtok(NULL, " ,\t\n\r"); + + if (nCmdShow == SW_SHOWMINIMIZED) + StartMinimized = TRUE; + + if (p1) + { + if (strlen(p1) > 5) + { + if (_stricmp(p1, "StartMinimized") == 0) + StartMinimized = TRUE; + + if (p2) Sessno = atoi(p2); + if (p3) sscanf(p3,"%x", &applflags); + } + else + { + if (p2) + { + if (strlen(p2) > 5) + { + if (_stricmp(p2, "StartMinimized") == 0) + StartMinimized = TRUE; + + if (p1) Sessno = atoi(p1); + if (p3) sscanf(p3,"%x", &applflags); + } + } + else + { + if (p3) + { + if (strlen(p3) > 5) + { + if (_stricmp(p3, "StartMinimized") == 0) + StartMinimized = TRUE; + + if (p1) Sessno = atoi(p1); + if (p2) sscanf(p2,"%x", &applflags); + } + } + } + } + } +*/ + sscanf(lpCmdLine,"%d %x",&Sessno, &applflags); + + if (!InitApplication(hInstance)) + return (FALSE); + + if (!InitInstance(hInstance, nCmdShow)) + return (FALSE); + + // Main message loop: + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + // Save Config + + retCode = RegCreateKeyEx(REGTREE, + Key, + 0, // Reserved + 0, // Class + 0, // Options + KEY_ALL_ACCESS, + NULL, // Security Attrs + &hKey, + &disp); + + if (retCode == ERROR_SUCCESS) + { + retCode = RegSetValueEx(hKey,"AutoConnect",0,REG_DWORD,(BYTE *)&AUTOCONNECT,4); + retCode = RegSetValueEx(hKey,"PortMask",0,REG_BINARY,(BYTE *)&portmask, 8); + retCode = RegSetValueEx(hKey,"Bells",0,REG_DWORD,(BYTE *)&Bells,4); + retCode = RegSetValueEx(hKey,"StripLF",0,REG_DWORD,(BYTE *)&StripLF,4); + retCode = RegSetValueEx(hKey,"SendDisconnected",0,REG_DWORD,(BYTE *)&SendDisconnected,4); + retCode = RegSetValueEx(hKey,"MTX",0,REG_DWORD,(BYTE *)&mtxparam,4); + retCode = RegSetValueEx(hKey,"MCOM",0,REG_DWORD,(BYTE *)&mcomparam,4); + retCode = RegSetValueEx(hKey,"MUIONLY",0,REG_DWORD,(BYTE *)&monUI,4); + retCode = RegSetValueEx(hKey,"Split",0,REG_BINARY,(BYTE *)&Split,sizeof(Split)); + retCode = RegSetValueEx(hKey,"MONColour",0,REG_DWORD,(BYTE *)&MonitorColour,4); + retCode = RegSetValueEx(hKey,"MonitorNODES",0,REG_DWORD,(BYTE *)&MonitorNODES,4); + + wsprintf(Size,"%d,%d,%d,%d",Rect.left,Rect.right,Rect.top,Rect.bottom); + retCode = RegSetValueEx(hKey,"Size",0,REG_SZ,(BYTE *)&Size, strlen(Size)); + + RegCloseKey(hKey); + } + + KillTimer(NULL, TimerHandle); + + CloseBPQ32(); // Close Ext Drivers if last bpq32 process + + return (msg.wParam); +} + +// + +// +// FUNCTION: InitApplication(HANDLE) +// +// PURPOSE: Initializes window data and registers window class +// +// COMMENTS: +// +// In this function, we initialize a window class by filling out a data +// structure of type WNDCLASS and calling either RegisterClass or +// the internal MyRegisterClass. +// +BOOL InitApplication(HINSTANCE hInstance) +{ + WNDCLASS wc; + + bgBrush = CreateSolidBrush(BGCOLOUR); + + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WndProc; + + wc.cbClsExtra = 0; + wc.cbWndExtra = DLGWINDOWEXTRA; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( BPQICON ) ); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = bgBrush; + + wc.lpszMenuName = NULL; + wc.lpszClassName = ClassName; + + return (RegisterClass(&wc)); + +} + +HMENU hMenu, hPopMenu1, hPopMenu2, hPopMenu3; // handle of menu + +VOID SetupRTFHddr() +{ + int i, n; + char RTFColours[3000]; + char Temp[1000]; + + // Set up RTF Header, including Colours String; + + memcpy(RTFColours, "{\\colortbl ;", 12); + n = 12; + + for (i = 1; i < 100; i++) + { + COLORREF Colour = Colours[i]; + n += wsprintf(&RTFColours[n], "\\red%d\\green%d\\blue%d;", GetRValue(Colour), GetGValue(Colour),GetBValue(Colour)); + } + + RTFColours[n++] = '}'; + RTFColours[n] = 0; + +// strcpy(RTFHeader, "{\\rtf1\\deff0{\\fonttbl{\\f0\\fmodern\\fprq1\\fcharset204 ;}}"); + wsprintf(RTFHeader, "{\\rtf1\\deff0{\\fonttbl{\\f0\\fprq1\\cpg%d\\fcharset%d %s;}}", CodePage, CharSet, FontName); + strcat(RTFHeader, RTFColours); + wsprintf(Temp, "\\viewkind4\\uc1\\pard\\f0\\fs%d", FontSize); + strcat(RTFHeader, Temp); + + RTFHddrLen = strlen(RTFHeader); +} + + +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + int i, n; + uint64_t tempmask=0x0; + char msg[50]; + int retCode,Type,Vallen; + HKEY hKey=0; + char Size[80]; + TEXTMETRIC tm; + HDC dc; + struct RTFTerm * OPData; + struct PORTCONTROL * PORT; + + hInst = hInstance; // Store instance handle in our global variable + + // 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"); + } + + REGTREE = GetRegistryKey(); + + MinimizetoTray=GetMinimizetoTrayFlag(); + + // Create a dialog box as the main window + + hWnd=CreateDialog(hInst,ClassName,0,NULL); + + if (!hWnd) + return (FALSE); + + MainWnd=hWnd; + + // Retrieve the handlse to the edit controls. + + hwndInput = GetDlgItem(hWnd, 118); +// hwndOutput = GetDlgItem(hWnd, 117); + hwndSplit = GetDlgItem(hWnd, 119); + hwndMon = GetDlgItem(hWnd, 116); + + // Set our own WndProcs for the controls. + + wpOrigInputProc = (WNDPROC) SetWindowLong(hwndInput, GWL_WNDPROC, (LONG) InputProc); + wpOrigMonProc = (WNDPROC)SetWindowLong(hwndMon, GWL_WNDPROC, (LONG)MonProc); + wpOrigSplitProc = (WNDPROC)SetWindowLong(hwndSplit, GWL_WNDPROC, (LONG)SplitProc); + + // Get config from Registry + + wsprintf(Key,"SOFTWARE\\G8BPQ\\BPQ32\\BPQTerminal\\Session%d",Sessno); + + retCode = RegOpenKeyEx (REGTREE, + Key, + 0, + KEY_QUERY_VALUE, + &hKey); + + if (retCode == ERROR_SUCCESS) + { + Vallen=4; + retCode = RegQueryValueEx(hKey,"MTX",0, + (ULONG *)&Type,(UCHAR *)&mtxparam,(ULONG *)&Vallen); + + Vallen=4; + retCode = RegQueryValueEx(hKey,"MUIONLY",0, + (ULONG *)&Type,(UCHAR *)&monUI,(ULONG *)&Vallen); + + Vallen=4; + retCode = RegQueryValueEx(hKey,"MCOM",0, + (ULONG *)&Type,(UCHAR *)&mcomparam,(ULONG *)&Vallen); + + Vallen=8; + retCode = RegQueryValueEx(hKey,"PortMask",0, + (ULONG *)&Type,(UCHAR *)&tempmask,(ULONG *)&Vallen); + + Vallen=4; + retCode = RegQueryValueEx(hKey,"AutoConnect",0, + (ULONG *)&Type,(UCHAR *)&AUTOCONNECT,(ULONG *)&Vallen); + + Vallen=4; + retCode = RegQueryValueEx(hKey,"MONColour",0, + (ULONG *)&Type,(UCHAR *)&MonitorColour,(ULONG *)&Vallen); + + Vallen=4; + retCode = RegQueryValueEx(hKey,"MonitorNODES",0, + (ULONG *)&Type,(UCHAR *)&MonitorNODES,(ULONG *)&Vallen); + + Vallen=4; + retCode = RegQueryValueEx(hKey,"Bells",0, + (ULONG *)&Type,(UCHAR *)&Bells,(ULONG *)&Vallen); + + Vallen=4; + retCode = RegQueryValueEx(hKey,"StripLF",0, + (ULONG *)&Type,(UCHAR *)&StripLF,(ULONG *)&Vallen); + + Vallen=4; + retCode = RegQueryValueEx(hKey, "SendDisconnected",0, + (ULONG *)&Type,(UCHAR *)&StripLF,(ULONG *)&Vallen); + + + + Vallen=8; + retCode = RegQueryValueEx(hKey,"Split",0, + (ULONG *)&Type,(UCHAR *)&Split,(ULONG *)&Vallen); + + Vallen=80; + retCode = RegQueryValueEx(hKey,"Size",0, + (ULONG *)&Type,(UCHAR *)&Size,(ULONG *)&Vallen); + + sscanf(Size,"%d,%d,%d,%d",&Rect.left,&Rect.right,&Rect.top,&Rect.bottom); + + Vallen=99; + retCode = RegQueryValueEx(hKey, "FontName", 0, &Type, FontName, &Vallen); + + if (FontName[0] == 0) + strcpy(FontName, "FixedSys"); + + Vallen=4; + retCode = RegQueryValueEx(hKey, "CharSet", 0, &Type, (UCHAR *)&CharSet, &Vallen); + + Vallen=4; + retCode = RegQueryValueEx(hKey, "CodePage", 0, &Type, (UCHAR *)&CodePage, &Vallen); + + Vallen=4; + retCode = RegQueryValueEx(hKey, "FontSize", 0, &Type, (UCHAR *)&FontSize, &Vallen); + + Vallen=4; + retCode = RegQueryValueEx(hKey, "FontWidth", 0, &Type, (UCHAR *)&FontWidth, &Vallen); + + RegCloseKey(hKey); + } + + OutputData.CharWidth = FontWidth; + + if (Rect.right < 100 || Rect.bottom < 100) + { + GetWindowRect(hWnd, &Rect); + } + + Height = Rect.bottom-Rect.top; + Width = Rect.right-Rect.left; + +#pragma warning(push) +#pragma warning(disable:4244) + SplitPos=Height*Split; +#pragma warning(pop) + + SetupRTFHddr(); + + // Create a Rich Text Control + + OPData = &OutputData; + + OPData->SendHeader = TRUE; + OPData->Finished = TRUE; + OPData->CurrentColour = 1; + + LoadLibrary("riched20.dll"); + + hwndOutput = CreateWindowEx(WS_EX_CLIENTEDGE, RICHEDIT_CLASS, "", + WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_NOHIDESEL | WS_VSCROLL | ES_READONLY, + 6,145,290,130, MainWnd, NULL, hInstance, NULL); + + // Register for Mouse Events for Copy/Paste + + SendMessage(hwndOutput, EM_SETEVENTMASK, (WPARAM)0, (LPARAM)ENM_MOUSEEVENTS | ENM_SCROLLEVENTS | ENM_KEYEVENTS); + SendMessage(hwndOutput, EM_EXLIMITTEXT, 0, MAXLINES * LINELEN); + + trayMenu = CreatePopupMenu(); + + AppendMenu(trayMenu,MF_STRING,40000,"Copy"); + + MoveWindow(hWnd,Rect.left,Rect.top, Rect.right-Rect.left, Rect.bottom-Rect.top, TRUE); + + MoveWindows(); + + Stream=FindFreeStream(); + + if (Stream == 255) + { + MessageBox(NULL,"No free streams available",NULL,MB_OK); + return (FALSE); + } + + // + // Register message for posting by BPQDLL + // + + BPQMsg = RegisterWindowMessage(BPQWinMsg); + + // + // Enable Async notification + // + + BPQSetHandle(Stream, hWnd); + + GetVersionInfo(NULL); + + wsprintf(Title,"BPQTerminal Version %s - using stream %d", VersionString, Stream); + + SetWindowText(hWnd,Title); + + +// Sets Application Flags and Mask for stream. (BPQHOST function 1) +// AH = 1 Set application mask to value in DL (or even DX if 16 +// applications are ever to be supported). +// +// Set application flag(s) to value in CL (or CX). +// whether user gets connected/disconnected messages issued +// by the node etc. +// +// Top bit of flags controls monitoring + + hMenu=GetMenu(hWnd); + +// if (applmask & 0x01) CheckMenuItem(hMenu,BPQAPPL1,MF_CHECKED); +// if (applmask & 0x02) CheckMenuItem(hMenu,BPQCHAT,MF_CHECKED); +// if (applmask & 0x04) CheckMenuItem(hMenu,BPQAPPL3,MF_CHECKED); +// if (applmask & 0x08) CheckMenuItem(hMenu,BPQAPPL4,MF_CHECKED); +// if (applmask & 0x10) CheckMenuItem(hMenu,BPQAPPL5,MF_CHECKED); +// if (applmask & 0x20) CheckMenuItem(hMenu,BPQAPPL6,MF_CHECKED); +// if (applmask & 0x40) CheckMenuItem(hMenu,BPQAPPL7,MF_CHECKED); +// if (applmask & 0x80) CheckMenuItem(hMenu,BPQAPPL8,MF_CHECKED); + +// CMD_TO_APPL EQU 1B ; PASS COMMAND TO APPLICATION +// MSG_TO_USER EQU 10B ; SEND 'CONNECTED' TO USER +// MSG_TO_APPL EQU 100B ; SEND 'CONECTED' TO APPL +// 0x40 = Send Keepalives + +// if (applflags & 0x01) CheckMenuItem(hMenu,BPQFLAGS1,MF_CHECKED); +// if (applflags & 0x02) CheckMenuItem(hMenu,BPQFLAGS2,MF_CHECKED); +// if (applflags & 0x04) CheckMenuItem(hMenu,BPQFLAGS3,MF_CHECKED); +// if (applflags & 0x40) CheckMenuItem(hMenu,BPQFLAGS4,MF_CHECKED); + + + hPopMenu1=GetSubMenu(hMenu,1); + + for (n=1;n <= GetNumberofPorts();n++) + { + PORT = GetPortTableEntryFromSlot(n); + + i = PORT->PORTNUMBER; + + sprintf(msg,"Port %d %s ",i, PORT->PORTDESCRIPTION); + + if (tempmask & ((uint64_t)1<<(i-1))) + { + AppendMenu(hPopMenu1,MF_STRING | MF_CHECKED,BPQBASE + i,msg); + portmask |= ((uint64_t)1 <<( i-1)); + } + else + AppendMenu(hPopMenu1,MF_STRING | MF_UNCHECKED,BPQBASE + i,msg); + } + + if (mtxparam & 1) + CheckMenuItem(hMenu,BPQMTX,MF_CHECKED); + else + CheckMenuItem(hMenu,BPQMTX,MF_UNCHECKED); + + CheckMenuItem(hMenu, BPQMCOM, (mcomparam) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MUIONLY, (monUI) ? MF_CHECKED : MF_UNCHECKED); + + if (AUTOCONNECT) + CheckMenuItem(hMenu,BPQAUTOCONNECT,MF_CHECKED); + else + CheckMenuItem(hMenu,BPQAUTOCONNECT,MF_UNCHECKED); + + if (Bells & 1) + CheckMenuItem(hMenu,BPQBELLS, MF_CHECKED); + else + CheckMenuItem(hMenu,BPQBELLS, MF_UNCHECKED); + + if (SendDisconnected & 1) + CheckMenuItem(hMenu,BPQSendDisconnected, MF_CHECKED); + else + CheckMenuItem(hMenu,BPQSendDisconnected, MF_UNCHECKED); + + if (StripLF & 1) + CheckMenuItem(hMenu,BPQStripLF, MF_CHECKED); + else + CheckMenuItem(hMenu,BPQStripLF, MF_UNCHECKED); + + CheckMenuItem(hMenu,BPQMNODES, (MonitorNODES) ? MF_CHECKED : MF_UNCHECKED); + + CheckMenuItem(hMenu,MONCOLOUR, (MonitorColour) ? MF_CHECKED : MF_UNCHECKED); + + DrawMenuBar(hWnd); + + if (portmask) applflags |= 0x80; + + SetAppl(Stream, applflags, applmask); + + SetTraceOptions64(portmask, mtxparam, mcomparam, monUI); + + DragCursor = LoadCursor(hInstance, "IDC_DragSize"); + Cursor = LoadCursor(NULL, IDC_ARROW); + + GetCallsign(Stream, callsign); + + if (MinimizetoTray) + { + // Set up Tray ICON + + wsprintf(Title,"BPQTerminal Stream %d",Stream); + AddTrayMenuItem(hWnd, Title); + } + + if ((nCmdShow == SW_SHOWMINIMIZED) || (nCmdShow == SW_SHOWMINNOACTIVE)) + if (MinimizetoTray) + ShowWindow(hWnd, SW_HIDE); + else + ShowWindow(hWnd, nCmdShow); + else + ShowWindow(hWnd, nCmdShow); + + UpdateWindow(hWnd); + + CheckTimer(); + + TimerHandle = SetTimer(NULL, 0, 10000, lpTimerFunc); + + dc = GetDC(hwndOutput); + GetTextMetrics(dc, &tm); + + return (TRUE); +} + +// +// FUNCTION: WndProc(HWND, unsigned, WORD, LONG) +// +// PURPOSE: Processes messages for the main window. +// + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int wmId, wmEvent; + LPRECT lprc; + UCHAR Buffer[1000]; + UCHAR * buf = Buffer; + TEXTMETRIC tm; + int i, y; + LPMEASUREITEMSTRUCT lpmis; + LPDRAWITEMSTRUCT lpdis; + + + if (message == BPQMsg) + { + if (lParam & BPQDataAvail) + DoReceivedData(hWnd); + + if (lParam & BPQMonitorAvail) + DoMonData(hWnd); + + if (lParam & BPQStateChange) + DoStateChange(hWnd); + + return (0); + } + + switch (message) { + + case WM_CTLCOLOREDIT: + + if (OutputData.Scrolled) + { + HDC hdcStatic = (HDC)wParam; + SetBkMode(hdcStatic, TRANSPARENT); + + return (LONG)GetStockObject(LTGRAY_BRUSH); + } + return (DefWindowProc(hWnd, message, wParam, lParam)); + + case WM_NOTIFY: + { + const MSGFILTER * pF = (MSGFILTER *)lParam; + POINT pos; + CHARRANGE Range; + + if(pF->nmhdr.hwndFrom == hwndOutput) + { + if(pF->msg == WM_VSCROLL) + { +// OutputData.Thumb = SendMessage(hwndOutput, EM_GETTHUMB, 0, 0); + DoRefresh(&OutputData); +// return TRUE; + } + + if(pF->msg == WM_KEYUP) + { + if (pF->wParam == VK_PRIOR || pF->wParam == VK_NEXT) + { +// OutputData.Thumb = SendMessage(hwndOutput, EM_GETTHUMB, 0, 0); + DoRefresh(&OutputData); + } + } + + if(pF->msg == WM_RBUTTONDOWN) + { + // Only allow popup if something is selected + + SendMessage(hwndOutput, EM_EXGETSEL , 0, (WPARAM)&Range); + if (Range.cpMin == Range.cpMax) + return TRUE; + + GetCursorPos(&pos); + TrackPopupMenu(trayMenu, 0, pos.x, pos.y, 0, hWnd, 0); + return TRUE; + } + } + break; + } + + + + case WM_MEASUREITEM: + + lpmis = (LPMEASUREITEMSTRUCT) lParam; + + // Set the height of the list box items. + + // lpmis->itemHeight = 15; + return TRUE; + + case WM_DRAWITEM: + + lpdis = (LPDRAWITEMSTRUCT) lParam; + + // If there are no list box items, skip this message. + + if (lpdis->itemID == -1) + { + return TRUE; + } + + switch (lpdis->itemAction) + { + case ODA_SELECT: + case ODA_DRAWENTIRE: + + // if Chat Console, and message has a colour eacape, action it + + SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID, (LPARAM) Buffer); + + GetTextMetrics(lpdis->hDC, &tm); + + if (lpdis->hwndItem == hwndOutput) + { + CharWidth = tm.tmAveCharWidth; + maxlinelen = ClientWidth/CharWidth - 1; + } + + y = (lpdis->rcItem.bottom + lpdis->rcItem.top - tm.tmHeight) / 2; + + if (Buffer[0] == 0x1b) + { + SetTextColor(lpdis->hDC, Colours[Buffer[1] - 10]); + buf += 2; + } +// SetBkColor(lpdis->hDC, 0); + + TextOut(lpdis->hDC, + 6, + y, + buf, + strlen(buf)); + + // SetTextColor(lpdis->hDC, OldColour); + + break; + } + + return TRUE; + + case WM_ACTIVATE: + + //fActive = LOWORD(wParam); // activation flag + //fMinimized = (BOOL) HIWORD(wParam); // minimized flag + // hwnd = (HWND) lParam; // window handle + + SetFocus(hwndInput); + break; + + + + case WM_COMMAND: + + wmId = LOWORD(wParam); // Remember, these are... + wmEvent = HIWORD(wParam); // ...different for Win32! + + //Parse the menu selections: + + if (wmId > BPQBASE && wmId < BPQBASE + 64) + { + TogglePort(hWnd,wmId,(uint64_t)1 << (wmId - (BPQBASE + 1))); + break; + } + + switch (wmId) { + + case 40000: + { + int len=0; + HGLOBAL hMem; + char * ptr; + CHARRANGE Range; + + // Copy Rich Text Selection to Clipboard + + SendMessage(hwndOutput, EM_EXGETSEL , 0, (WPARAM)&Range); + + hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, Range.cpMax - Range.cpMin + 1); + + if (hMem != 0) + { + ptr=GlobalLock(hMem); + + if (OpenClipboard(MainWnd)) + { + len = SendMessage(hwndOutput, EM_GETSELTEXT , 0, (WPARAM)ptr); + + GlobalUnlock(hMem); + EmptyClipboard(); + SetClipboardData(CF_TEXT,hMem); + CloseClipboard(); + } + } + else + GlobalFree(hMem); + + SetFocus(hwndInput); + return TRUE; + } + + case ID_SETUP_FONT: + + DialogBox(hInst, MAKEINTRESOURCE(IDD_FONT), hWnd, FontConfigWndProc); + break; + + + case BPQMTX: + + ToggleMTX(hWnd); + break; + + case BPQMCOM: + + ToggleMCOM(hWnd); + break; + + case MUIONLY: + + ToggleMUI(hWnd); + break; + + case BPQCONNECT: + + SessionControl(Stream, 1, 0); + break; + + case BPQDISCONNECT: + + SessionControl(Stream, 2, 0); + break; + + + case ID_ACTION_RESETWINDOWSPLIT: + + Split = 0.5; + SplitPos=Height*Split; + MoveWindows(); + + break; + + case BPQAUTOCONNECT: + + ToggleAutoConnect(hWnd); + break; + + case BPQBELLS: + + ToggleParam(hWnd, &Bells, BPQBELLS); + break; + + case BPQStripLF: + + ToggleParam(hWnd, &StripLF, BPQStripLF); + break; + + case BPQLogOutput: + + ToggleParam(hWnd, &LogOutput, BPQLogOutput); + break; + + case CHATTERM: + + ToggleParam(hWnd, &ChatMode, CHATTERM); + break; + + + case BPQSendDisconnected: + + ToggleParam(hWnd, &SendDisconnected, BPQSendDisconnected); + break; + + case BPQMNODES: + + ToggleParam(hWnd, &MonitorNODES, BPQMNODES); + break; + + case MONCOLOUR: + + ToggleParam(hWnd, &MonitorColour, MONCOLOUR); + break; + + case BPQLogMonitor: + + ToggleParam(hWnd, &LogMonitor, BPQLogMonitor); + break; + + case BPQCLEARMON: + + SendMessage(hwndMon,LB_RESETCONTENT, 0, 0); + break; + + case BPQCLEAROUT: + + for (i = 0; i < MAXLINES; i++) + { + OutputData.OutputScreen[i][0] = 0; + } + + OutputData.CurrentLine = 0; + DoRefresh(&OutputData); + + break; + + case BPQCOPYMON: + + CopyListToClipboard(hwndMon); + break; + + case BPQCOPYOUT: + + CopyRichTextToClipboard(hwndOutput); + break; + + case BPQHELP: + + ShellExecute(hWnd,"open", + "http://www.cantab.net/users/john.wiseman/Documents/BPQTerminal.htm", + "", NULL, SW_SHOWNORMAL); + break; + + default: + + return 0; + + } + + case WM_SYSCOMMAND: + + wmId = LOWORD(wParam); // Remember, these are... + wmEvent = HIWORD(wParam); // ...different for Win32! + + switch (wmId) + { + case SC_MINIMIZE: + + if (MinimizetoTray) + return ShowWindow(hWnd, SW_HIDE); + + default: + + return (DefWindowProc(hWnd, message, wParam, lParam)); + } + + case WM_SIZING: + + lprc = (LPRECT) lParam; + + Height = lprc->bottom-lprc->top; + Width = lprc->right-lprc->left; + + SplitPos=Height*Split; + + MoveWindows(); + + return TRUE; + + case WM_SIZE: + + MoveWindows(); + return TRUE; + + case WM_DESTROY: + + // Remove the subclass from the edit control. + + GetWindowRect(hWnd, &Rect); // For save soutine + + SetWindowLong(hwndInput, GWL_WNDPROC, + (LONG) wpOrigInputProc); + + SessionControl(Stream, 2, 0); + DeallocateStream(Stream); + PostQuitMessage(0); + + if (MinimizetoTray) + DeleteTrayMenuItem(hWnd); + + break; + + default: + return (DefWindowProc(hWnd, message, wParam, lParam)); + + } + return (0); +} + +static char * KbdStack[20]; + +int StackIndex=0; + +LRESULT APIENTRY InputProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + char DisplayLine[200] = "\x1b\xb"; + + if (uMsg == WM_CTLCOLOREDIT) + { + HBRUSH Brush = CreateSolidBrush(RGB(0, 255, 0)); + HDC hdcStatic = (HDC)wParam; + SetTextColor(hdcStatic, RGB(0, 0, 0)); + SetBkMode(hdcStatic, TRANSPARENT); + + return (LONG)Brush; + } + + + if (uMsg == WM_KEYUP) + { + unsigned int i; + +// Debugprintf("5%x", LOBYTE(HIWORD(lParam))); + + if (LOBYTE(HIWORD(lParam)) == 0x48 && wParam == 0x26) + { + // Scroll up + + if (KbdStack[StackIndex] == NULL) + return TRUE; + + SendMessage(hwndInput, WM_SETTEXT,0,(LPARAM)(LPCSTR) KbdStack[StackIndex]); + + for (i = 0; i < strlen(KbdStack[StackIndex]); i++) + { + SendMessage(hwndInput, WM_KEYDOWN, VK_RIGHT, 0); + SendMessage(hwndInput, WM_KEYUP, VK_RIGHT, 0); + } + + StackIndex++; + if (StackIndex == 20) + StackIndex = 19; + + return TRUE; + } + + if (LOBYTE(HIWORD(lParam)) == 0x50 && wParam == 0x28) + { + // Scroll up + + StackIndex--; + if (StackIndex < 0) + StackIndex = 0; + + if (KbdStack[StackIndex] == NULL) + return TRUE; + + SendMessage(hwndInput,WM_SETTEXT,0,(LPARAM)(LPCSTR) KbdStack[StackIndex]); + + for (i = 0; i < strlen(KbdStack[StackIndex]); i++) + { + SendMessage(hwndInput, WM_KEYDOWN, VK_RIGHT, 0); + SendMessage(hwndInput, WM_KEYUP, VK_RIGHT, 0); + } + + return TRUE; + } + } + + + + if (uMsg == WM_CHAR) + { + if (wParam == 13) + { + int i; + + // + // if not connected, and autoconnect is + // enabled, connect now + + if (!CONNECTED && AUTOCONNECT) + SessionControl(Stream, 1, 0); + + kbptr=SendMessage(hwndInput,WM_GETTEXT,159,(LPARAM) (LPCSTR) kbbuf); + + // Stack it + + StackIndex = 0; + + if (KbdStack[19]) + free(KbdStack[19]); + + for (i = 18; i >= 0; i--) + { + KbdStack[i+1] = KbdStack[i]; + } + + KbdStack[0] = _strdup(kbbuf); + + kbbuf[kbptr]=13; + + SlowTimer = 0; + + // Echo, with set Black escape + + memcpy(&DisplayLine[2], kbbuf, kbptr+1); + + if (OutputData.Scrolled) + { + POINT Point; + Point.x = 0; + Point.y = 25000; // Should be plenty for any font + + SendMessage(hwndOutput, EM_SETSCROLLPOS, 0, (LPARAM) &Point); + OutputData.Scrolled = FALSE; + } + + WritetoOutputWindow(&OutputData, DisplayLine, kbptr+3); + DoRefresh(&OutputData); + + + // Replace null with CR, and send to Node + + SendMsg(Stream, &kbbuf[0], kbptr+1); + + SendMessage(hwndInput,WM_SETTEXT,0,(LPARAM)(LPCSTR) ""); + + return 0; + } + if (wParam == 0x1a) // Ctrl/Z + { + // + // if not connected, and autoconnect is + // enabled, connect now + + if (!CONNECTED && AUTOCONNECT) + SessionControl(Stream, 1, 0); + + kbbuf[0]=0x1a; + kbbuf[1]=13; + + SendMsg(Stream, &kbbuf[0], 2); + + SendMessage(hwndInput,WM_SETTEXT,0,(LPARAM)(LPCSTR) ""); + + return 0; + } + + } + + return CallWindowProc(wpOrigInputProc, hwnd, uMsg, wParam, lParam); +} + +//int FirstItem=-1, LastItem=-1, SELECTING=FALSE, MOVED=FALSE, LastSelected=0; + +LRESULT APIENTRY MonProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST) + return TRUE; + + return CallWindowProc(wpOrigMonProc, hwnd, uMsg, wParam, lParam); +} + +LRESULT APIENTRY SplitProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + int xPos, yPos; + + switch (uMsg) { + + case WM_LBUTTONDOWN: + + SetCapture(hwnd); + return 0; + + case WM_LBUTTONUP: + + xPos = LOWORD(lParam); // horizontal position of cursor + yPos = lParam >> 16; // vertical position of cursor + + SplitPos = SplitPos + yPos - 5; + + if (SplitPos < 0) SplitPos = 0; + + Split=SplitPos; + Split=Split/Height; + + ReleaseCapture(); + MoveWindows(); + DoRefresh(&OutputData); + return 0; + + case WM_MOUSEMOVE: + + // Used to size split between Monitor and Output Windows + + SetCursor(DragCursor); + break; + } + return CallWindowProc(wpOrigSplitProc, hwnd, uMsg, wParam, lParam); +} + + + + +DoStateChange(HWND hWnd) +{ + int port, sesstype, paclen, maxframe, l4window; + + // Get current Session State. Any state changed is ACK'ed + // automatically. See BPQHOST functions 4 and 5. + + SessionState(Stream, &state, &change); + + if (change == 1) + { + if (state == 1) + { + // Connected + + CONNECTED = TRUE; + SlowTimer = 0; + + // GetCallsign(Stream, callsign); + + GetConnectionInfo(Stream, callsign, + &port, &sesstype, &paclen, + &maxframe, &l4window); + + + wsprintf(Title,"BPQTerminal Version %s - using stream %d - Connected to %s",VersionString,Stream,callsign); + SetWindowText(hWnd,Title); + DisableConnectMenu(hWnd); + EnableDisconnectMenu(hWnd); + + } + else + { + CONNECTED=FALSE; + wsprintf(Title,"BPQTerminal Version %s - using stream %d - Disconnected",VersionString,Stream); + SetWindowText(hWnd,Title); + DisableDisconnectMenu(hWnd); + EnableConnectMenu(hWnd); + + if (SendDisconnected) + { + WritetoOutputWindow(&OutputData, "*** Disconnected\r", 17); + DoRefresh(&OutputData); + } + } + } + + return (0); + +} + +DoReceivedData(HWND hWnd) +{ + char Msg[300]; + + if (RXCount(Stream) > 0) + { + do { + + GetMsg(Stream, &Msg[0],&len,&count); + WritetoOutputWindow(&OutputData, Msg, len); + DoRefresh(&OutputData); + + SlowTimer = 0; + + } while (count > 0); + } + return (0); +} +DWORD CALLBACK EditStreamCallback(DWORD_PTR Cookie, LPBYTE lpBuff, LONG cb, PLONG pcb) +{ + struct RTFTerm * OPData = (struct RTFTerm *)Cookie; + int ReqLen = cb; + int i; + int Line; + +// if (cb != 4092) +// return 0; + + if (OPData->SendHeader) + { + // Return header + + memcpy(lpBuff, RTFHeader, RTFHddrLen); + *pcb = RTFHddrLen; + OPData->SendHeader = FALSE; + OPData->Finished = FALSE; + OPData->Index = 0; + return 0; + } + + if (OPData->Finished) + { + *pcb = 0; + return 0; + } + +/* + if (BufferLen > cb) + { + memcpy(lpBuff, &Buffer[Offset], cb); + BufferLen -= cb; + Offset += cb; + *pcb = cb; + return 0; + } + + memcpy(lpBuff, &Buffer[Offset], BufferLen); + + *pcb = BufferLen; +*/ + + // Return 10 line at a time + + for (i = 0; i < 10; i++); + { + Line = OPData->Index++ + OPData->CurrentLine - MAXLINES; + + if (Line <0) + Line = Line + MAXLINES; + + wsprintf(lpBuff, "\\cf%d ", OPData->Colourvalue[Line]); + strcat(lpBuff, OPData->OutputScreen[Line]); + strcat(lpBuff, "\\line"); + + if (OPData->Index == MAXLINES) + { + OPData->Finished = TRUE; + strcat(lpBuff, "}"); + i = 10; + } + } + *pcb = strlen(lpBuff); + return 0; +} + +VOID ForceRefresh(struct RTFTerm * OPData) +{ + OPData->Thumb = 25000; + DoRefresh(OPData); + OPData->Thumb = SendMessage(hwndOutput, EM_GETTHUMB, 0, 0); +} + +VOID DoRefresh(struct RTFTerm * OPData) +{ + EDITSTREAM es = {0}; + int Min, Max, Pos; + POINT Point; + SCROLLINFO ScrollInfo; + int LoopTrap = 0; + + if(WINE) + OPData->Thumb = 30000; + else + OPData->Thumb = SendMessage(hwndOutput, EM_GETTHUMB, 0, 0); + + Pos = OPData->Thumb + OutputBoxHeight; + + if (Pos > OPData->RTFHeight - 10) // Don't bother writing to screen if scrolled back + { + es.pfnCallback = EditStreamCallback; + es.dwCookie = (DWORD_PTR)OPData; + OPData->SendHeader = TRUE; + SendMessage(hwndOutput, EM_STREAMIN, SF_RTF, (LPARAM)&es); + } +// else +// Debugprintf("Pos %d RTFHeight %d - Not refreshing", Pos, OPData->RTFHeight); + + GetScrollRange(hwndOutput, SB_VERT, &Min, &Max); + ScrollInfo.cbSize = sizeof(ScrollInfo); + ScrollInfo.fMask = SIF_ALL; + + GetScrollInfo(hwndOutput, SB_VERT, &ScrollInfo); + +// Debugprintf("Thumb %d Pos %d Min %d Max %d nMax %d ClientH %d RTFHeight %d", +// OPData->Thumb, Pos, Min, Max, ScrollInfo.nMax, OutputBoxHeight, OPData->RTFHeight); + + if (OPData->FirstTime == FALSE) + { + // RTF Controls don't immediately scroll to end - don't know why. + + OPData->FirstTime = TRUE; + Point.x = 0; + Point.y = 25000; // Should be plenty for any font + + while (LoopTrap++ < 20) + { + SendMessage(hwndOutput, EM_SETSCROLLPOS, 0, (LPARAM) &Point); + } + + GetScrollRange(hwndOutput, SB_VERT, &Min, &Max); // Get Actual Height + OPData->RTFHeight = Max; + Point.x = 0; + Point.y = OPData->RTFHeight - ScrollInfo.nPage; + SendMessage(hwndOutput, EM_SETSCROLLPOS, 0, (LPARAM) &Point); + OPData->Thumb = SendMessage(hwndOutput, EM_GETTHUMB, 0, 0); + } + + Point.x = 0; + Point.y = OPData->RTFHeight - ScrollInfo.nPage; + + if (OPData->Thumb > (Point.y - 10)) // Don't Scroll if user has scrolled back + { +// Debugprintf("Scrolling to %d", Point.y); + SendMessage(hwndOutput, EM_SETSCROLLPOS, 0, (LPARAM) &Point); + if (OPData->Scrolled) + { + OPData->Scrolled = FALSE; + InvalidateRect(hwndInput, NULL, TRUE); + } + return; + } + +// Debugprintf("Thumb = %d Point.y = %d - Not Scrolling", OPData->Thumb, Point.y); + + if (!OPData->Scrolled) + { + OPData->Scrolled = TRUE; + InvalidateRect(hwndInput, NULL, TRUE); + } +} + +VOID AddLinetoWindow(struct RTFTerm * OPData, char * Line) +{ + int Len = strlen(Line); + char * ptr1 = Line; + char * ptr2; + int l, Index; + char LineCopy[LINELEN * 2]; + + if (Line[0] == 0x1b && Len > 1) + { + // Save Colour Char + + OPData->CurrentColour = Line[1] - 10; + ptr1 +=2; + Len -= 2; + } + + strcpy(OPData->OutputScreen[OPData->CurrentLine], ptr1); + + // Look for chars we need to escape (\ { }) + + ptr1 = OPData->OutputScreen[OPData->CurrentLine]; + Index = 0; + ptr2 = strchr(ptr1, '\\'); // Look for Backslash first, as we may add some later + + if (ptr2) + { + while (ptr2) + { + l = ++ptr2 - ptr1; + memcpy(&LineCopy[Index], ptr1, l); // Copy Including found char + Index += l; + LineCopy[Index++] = '\\'; + Len++; + ptr1 = ptr2; + ptr2 = strchr(ptr1, '\\'); + } + strcpy(&LineCopy[Index], ptr1); // Copy in rest + strcpy(OPData->OutputScreen[OPData->CurrentLine], LineCopy); + } + + ptr1 = OPData->OutputScreen[OPData->CurrentLine]; + Index = 0; + ptr2 = strchr(ptr1, '{'); + + if (ptr2) + { + while (ptr2) + { + l = ptr2 - ptr1; + memcpy(&LineCopy[Index], ptr1, l); + Index += l; + LineCopy[Index++] = '\\'; + LineCopy[Index++] = '{'; + Len++; + ptr1 = ++ptr2; + ptr2 = strchr(ptr1, '{'); + } + strcpy(&LineCopy[Index], ptr1); // Copy in rest + strcpy(OPData->OutputScreen[OPData->CurrentLine], LineCopy); + } + + ptr1 = OPData->OutputScreen[OPData->CurrentLine]; + Index = 0; + ptr2 = strchr(ptr1, '}'); // Look for Backslash first, as we may add some later + + if (ptr2) + { + while (ptr2) + { + l = ptr2 - ptr1; + memcpy(&LineCopy[Index], ptr1, l); // Copy + Index += l; + LineCopy[Index++] = '\\'; + LineCopy[Index++] = '}'; + Len++; + ptr1 = ++ptr2; + ptr2 = strchr(ptr1, '}'); + } + strcpy(&LineCopy[Index], ptr1); // Copy in rest + strcpy(OPData->OutputScreen[OPData->CurrentLine], LineCopy); + } + + + OPData->Colourvalue[OPData->CurrentLine] = OPData->CurrentColour; + OPData->LineLen[OPData->CurrentLine++] = Len; + if (OPData->CurrentLine >= MAXLINES) OPData->CurrentLine = 0; +} + +VOID WritetoOutputWindow(struct RTFTerm * OPData, char * Msg, int len) +{ + char * ptr1, * ptr2; + + if (PartLinePtr > LINELEN) + Msg[len++] = 13; // Force a newline + + if (PartLinePtr != 0) + { + OPData->CurrentLine--; // Overwrite part line in buffer + if (OPData->CurrentLine < 0) + OPData->CurrentLine = MAXLINES - 1; + + if (Msg[0] == 0x1b && len > 1) + { + Msg += 2; // Remove Colour Escape + len -= 2; + } + } + + memcpy(&readbuff[PartLinePtr], Msg, len); + + len += PartLinePtr; + + ptr1=&readbuff[0]; + readbuff[len]=0; + + if (Bells) + { + do { + ptr2=memchr(ptr1,7,len); + + if (ptr2) + { + *(ptr2)=32; + Beep(440,250); + } + } while (ptr2); + } + +lineloop: + + if (len > 0) + { + // copy text to buffer a line at a time + + ptr2=memchr(ptr1,13,len); + + if (ptr2 == 0) + { + // no newline. Move data to start of buffer and Save pointer + + PartLinePtr = len; + memmove(readbuff,ptr1,len); + AddLinetoWindow(OPData, ptr1); + return; + } + + *(ptr2++)=0; + + if (LogOutput) WriteMonitorLine(ptr1, ptr2 - ptr1); + + // If len is greater that screen with, fold + + if ((ptr2 - ptr1) > maxlinelen) + { + char * ptr3; + char * saveptr1 = ptr1; + int linelen = ptr2 - ptr1; + int foldlen; + char save; + + foldloop: + + ptr3 = ptr1 + maxlinelen; + + while(*ptr3!= 0x20 && ptr3 > ptr1) + { + ptr3--; + } + foldlen = ptr3 - ptr1 ; + + if (foldlen == 0) + { + // No space before, so split at width + + foldlen = maxlinelen; + ptr3 = ptr1 + maxlinelen; + + } + else + { + ptr3++ ; // Omit space + linelen--; + } + save = ptr1[foldlen]; + ptr1[foldlen] = 0; + + AddLinetoWindow(OPData, ptr1); + + ptr1[foldlen] = save; + linelen -= foldlen; + ptr1 = ptr3; + + if (linelen > maxlinelen) + goto foldloop; + + AddLinetoWindow(OPData, ptr1); + ptr1 = saveptr1; + + } + else + AddLinetoWindow(OPData, ptr1); + + + PartLinePtr=0; + + len-=(ptr2-ptr1); + + ptr1=ptr2; + + if ((len > 0) && StripLF) + { + if (*ptr1 == 0x0a) // Line Feed + { + ptr1++; + len--; + } + } + goto lineloop; + } +} + + +DoMonData(HWND hWnd) +{ + char * ptr1, * ptr2; + int index; + time_t stamp; + int len; + unsigned char buffer[1024] = "\x1b\xb", monbuff[512]; + + if (MONCount(Stream) > 0) + { + do { + + stamp=GetRaw(Stream, monbuff,&len,&count); + + if (MonitorColour) + { + if (monbuff[4] & 0x80) // TX + buffer[1] = 91; + else + buffer[1] = 17; + } + + // See if a NODES + + if (!MonitorNODES && monbuff[21] == 3 && monbuff[22] == 0xcf && monbuff[23] == 0xff) + len = 0; + else + { + len=DecodeFrame(monbuff,&buffer[2],stamp); + len +=2; + } + + ptr1=&buffer[0]; + + lineloop: + + if (len > 0) + { + // copy text to control a line at a time + + ptr2=memchr(ptr1,13,len); + + if (ptr2 == 0) + { + // no newline. Move data to start of buffer and Save pointer + + memmove(buffer,ptr1,len); + + return (0); + + } + else + { + *(ptr2++)=0; + + index=SendMessage(hwndMon,LB_ADDSTRING,0,(LPARAM)(LPCTSTR) ptr1 ); + + if (LogMonitor) WriteMonitorLine(ptr1, ptr2 - ptr1); + + if (index > 1200) + + do{ + + index=SendMessage(hwndMon,LB_DELETESTRING, 0, 0); + + } while (index > 1000); + + SendMessage(hwndMon,LB_SETCARETINDEX,(WPARAM) index, MAKELPARAM(FALSE, 0)); + + len-=(ptr2-ptr1); + + ptr1=ptr2; + + goto lineloop; + } + } + + } while (count > 0); + } + return (0); +} + + + + + +int DisableConnectMenu(HWND hWnd) +{ + HMENU hMenu; // handle of menu + + hMenu=GetMenu(hWnd); + + EnableMenuItem(hMenu,BPQCONNECT,MF_GRAYED); + + return (0); +} +int DisableDisconnectMenu(HWND hWnd) +{ + HMENU hMenu; // handle of menu + + hMenu=GetMenu(hWnd); + + EnableMenuItem(hMenu,BPQDISCONNECT,MF_GRAYED); + return (0); +} + +int EnableConnectMenu(HWND hWnd) +{ + HMENU hMenu; // handle of menu + + hMenu=GetMenu(hWnd); + + EnableMenuItem(hMenu,BPQCONNECT,MF_ENABLED); + return (0); +} + +int EnableDisconnectMenu(HWND hWnd) +{ + HMENU hMenu; // handle of menu + + hMenu=GetMenu(hWnd); + + EnableMenuItem(hMenu,BPQDISCONNECT,MF_ENABLED); + + return (0); +} + +int ToggleAutoConnect(HWND hWnd) +{ + HMENU hMenu; // handle of menu + + hMenu=GetMenu(hWnd); + + AUTOCONNECT = !AUTOCONNECT; + + if (AUTOCONNECT) + + CheckMenuItem(hMenu,BPQAUTOCONNECT,MF_CHECKED); + + else + + CheckMenuItem(hMenu,BPQAUTOCONNECT,MF_UNCHECKED); + + return (0); + +} + +CopyScreentoBuffer(char * buff) +{ + + return (0); +} + +int TogglePort(HWND hWnd, int Item, uint64_t mask) +{ + portmask ^= mask; + + if (portmask & mask) + CheckMenuItem(hMenu,Item,MF_CHECKED); + else + CheckMenuItem(hMenu,Item,MF_UNCHECKED); + + if (portmask) + applflags |= 0x80; + else + applflags &= 0x7f; + + SetAppl(Stream,applflags,applmask); + + SetTraceOptions64(portmask, mtxparam, mcomparam, monUI); + + return (0); + +} +int ToggleMTX(HWND hWnd) +{ + mtxparam = mtxparam ^ 1; + + if (mtxparam & 1) + + CheckMenuItem(hMenu,BPQMTX,MF_CHECKED); + else + CheckMenuItem(hMenu,BPQMTX,MF_UNCHECKED); + + SetTraceOptions64(portmask, mtxparam, mcomparam, monUI); + + return (0); + +} +int ToggleMCOM(HWND hWnd) +{ + mcomparam = mcomparam ^ 1; + + CheckMenuItem(hMenu, BPQMCOM, (mcomparam) ? MF_CHECKED : MF_UNCHECKED); + SetTraceOptions64(portmask, mtxparam, mcomparam, monUI); + + return (0); + +} +int ToggleMUI(HWND hWnd) +{ + monUI = monUI ^ 1; + + CheckMenuItem(hMenu, MUIONLY, (monUI) ? MF_CHECKED : MF_UNCHECKED); + SetTraceOptions64(portmask, mtxparam, mcomparam, monUI); + + return (0); + +} +int ToggleParam(HWND hWnd, BOOL * Param, int Item) +{ + *Param = !(*Param); + + CheckMenuItem(hMenu,Item, (*Param) ? MF_CHECKED : MF_UNCHECKED); + + return (0); +} + +void MoveWindows() +{ + RECT rcMain, rcClient; + int ClientHeight, ClientWidth; + + if (hWnd == 0) + return; + + GetWindowRect(hWnd, &rcMain); + GetClientRect(hWnd, &rcClient); + + ClientHeight = rcClient.bottom; + ClientWidth = rcClient.right; + + if (ClientWidth == 0) // Minimized + return; + + OutputBoxHeight = ClientHeight - SplitPos - InputBoxHeight - SplitBarHeight - SplitBarHeight; + + MoveWindow(hwndMon,2, 0, ClientWidth-4, SplitPos, TRUE); + MoveWindow(hwndOutput,2, SplitPos+SplitBarHeight, ClientWidth-4, OutputBoxHeight, TRUE); + MoveWindow(hwndInput,2, ClientHeight-InputBoxHeight-2, ClientWidth-4, InputBoxHeight, TRUE); + MoveWindow(hwndSplit,0, SplitPos, ClientWidth, SplitBarHeight, TRUE); + + GetClientRect(hwndOutput, &rcClient); + + ClientHeight = rcClient.bottom; + ClientWidth = rcClient.right; + + if (ClientWidth > 16) + maxlinelen = ClientWidth/OutputData.CharWidth - 1; + + InvalidateRect(hWnd, NULL, TRUE); +} + +void CopyRichTextToClipboard(HWND hWnd) +{ + int len=0; + HGLOBAL hMem; + char * ptr; + + // Copy Rich Text to Clipboard + + len = SendMessage(hwndOutput, WM_GETTEXTLENGTH, 0, 0); + + hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, len + 1); + + if (hMem != 0) + { + ptr=GlobalLock(hMem); + + if (OpenClipboard(MainWnd)) + { + len = SendMessage(hwndOutput, WM_GETTEXT , len, (LPARAM)ptr); + + GlobalUnlock(hMem); + EmptyClipboard(); + SetClipboardData(CF_TEXT,hMem); + CloseClipboard(); + } + } + else + GlobalFree(hMem); +} + + +void CopyListToClipboard(HWND hWnd) +{ + int i,n, len=0; + HGLOBAL hMem; + char * ptr; + // + // Copy List Box to clipboard + // + + n = SendMessage(hWnd, LB_GETCOUNT, 0, 0); + + for (i=0; i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BPQTerminal.vcxproj b/BPQTerminal.vcxproj new file mode 100644 index 0000000..865304b --- /dev/null +++ b/BPQTerminal.vcxproj @@ -0,0 +1,154 @@ + + + + + Debug + Win32 + + + Relase Static + Win32 + + + Release + Win32 + + + + 18.0 + {04F2B9AD-4369-49EA-82EC-3C701C97C6D8} + Win32Proj + + + + Application + v145 + + + Application + v145 + + + Application + v145 + + + + + + + + + + + + + + + + <_ProjectFileVersion>18.0.12106.202 + + + Debug\ + $(Configuration)\ + true + true + + + Release\ + Release\ + true + true + + + $(Configuration)\ + $(Configuration)\ + false + true + + + + Disabled + ./;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USE_32BIT_TIME_T;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + true + Level3 + EditAndContinue + 4244;%(DisableSpecificWarnings) + + + S:\DEV\Source\BPQ32\cInclude;%(AdditionalIncludeDirectories) + + + Win32Bits\bpq32.lib;htmlhelp.lib;%(AdditionalDependencies) + c:\DevProgs\bpq32\BPQTerminal.exe + c:\bpq32\BPQTerminal.exe.manifest + true + Windows + MachineX86 + + + + + ./;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreaded + + Level3 + ProgramDatabase + 4244;%(DisableSpecificWarnings) + + + S:\DEV\Source\BPQ32\Include;%(AdditionalIncludeDirectories) + + + Win32Bits\bpq32.lib;htmlhelp.lib;%(AdditionalDependencies) + c:\DevProgs\bpq32\BPQTerminal.exe + c:\bpq32\BPQTerminal.exe.manifest + false + Windows + + true + MachineX86 + + + + + ..\Commonsource;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USE_32BIT_TIME_T;%(PreprocessorDefinitions) + MultiThreaded + + Level3 + ProgramDatabase + 4244;%(DisableSpecificWarnings) + + + S:\DEV\Source\BPQ32\Include;%(AdditionalIncludeDirectories) + + + ..\lib\bpq32.lib;htmlhelp.lib;%(AdditionalDependencies) + c:\DevProgs\bpq32\BPQTerminal.exe + c:\bpq32\BPQTerminal.exe.manifest + false + true + c:\DevProgs\bpq32\BPQTerminal.map + Windows + + true + MachineX86 + + + + + + + + + + + + \ No newline at end of file diff --git a/BPQWinAPP.c b/BPQWinAPP.c index e3e8f1d..d70ef68 100644 --- a/BPQWinAPP.c +++ b/BPQWinAPP.c @@ -80,22 +80,26 @@ VOID WriteMiniDump() #endif } -SYMBOL_INFO * symbol; + HANDLE process; -void printStack(void) +void printStack() { -#ifdef WIN32 -//#ifdef _DEBUG // So we can use on 98/2K - - unsigned int i; - void * stack[ 100 ]; + unsigned int i, n; + void * stack[ 100 ]; unsigned short frames; DWORD dwDisplacement; IMAGEHLP_LINE64 line; char * fptr; - Debugprintf("Stack Backtrace"); + + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; + + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol->MaxNameLen = MAX_SYM_NAME; + + Debugprintf("Stack Backtrace\r\n"); process = GetCurrentProcess(); @@ -106,42 +110,24 @@ void printStack(void) for( i = 0; i < frames; i++ ) { - SymGetLineFromAddr64(process, (DWORD64)stack[i], &dwDisplacement, &line); - SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol ); - - fptr = line.FileName + (int)strlen(line.FileName); // remove path - while (*fptr != '\\' && *fptr != '/') - fptr--; - - fptr++; - + n = SymGetLineFromAddr64(process, (DWORD64)stack[i], &dwDisplacement, &line); + n = SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol ); - Debugprintf( "%i: %s - %s Line %d Addr %p", frames - i - 1, symbol->Name, fptr, line.LineNumber, symbol->Address ); - } + if (line.FileName) + { + fptr = line.FileName + (int)strlen(line.FileName); // remove path + while (*fptr != '\\' && *fptr != '/') + fptr--; - free(symbol); + fptr++; -//#endif -#endif -} - -int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep) -{ - Debugprintf("in filter."); - printStack(); - if (code == EXCEPTION_ACCESS_VIOLATION) - { - Debugprintf("caught AV as expected."); - return EXCEPTION_EXECUTE_HANDLER; - } - else - { - Debugprintf("didn't catch AV, unexpected."); - return EXCEPTION_CONTINUE_SEARCH; - } + Debugprintf("%i: %s - %s Line %d Addr %p", frames - i - 1, symbol->Name, fptr, line.LineNumber, symbol->Address ); + } + } } +int inErrorhandling = 0; LONG WINAPI UnhandledExcepFilter(PEXCEPTION_POINTERS pExcepPointers) { @@ -149,27 +135,58 @@ LONG WINAPI UnhandledExcepFilter(PEXCEPTION_POINTERS pExcepPointers) IMAGEHLP_LINE64 line; char * fptr; + + time_t T; + struct tm * tm; + + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; + + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol->MaxNameLen = MAX_SYM_NAME; + + + T = time(NULL); + tm = gmtime(&T); + + if (inErrorhandling) + { + MessageBox(NULL,"Program Error in error handler - program closing. See Debug Log for details","BPQ32",MB_ICONSTOP); + + exit(0); + } + + inErrorhandling = 1; + if(pExcepPointers->ExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_C) return EXCEPTION_CONTINUE_EXECUTION; SymFromAddr( process, ((DWORD)pExcepPointers->ExceptionRecord->ExceptionAddress), 0, symbol ); - Debugprintf("Program error trapped\r\n"); + Debugprintf("\r\n\r\nProgram error trapped at %02d:%02d:%02d\r\n", tm->tm_hour, tm->tm_min, tm->tm_sec); SymGetLineFromAddr64(process, (DWORD)pExcepPointers->ExceptionRecord->ExceptionAddress, &dwDisplacement, &line); - fptr = line.FileName + (int)strlen(line.FileName); // remove path - while (*fptr != '\\' && *fptr != '/') - fptr--; + + if (line.FileName) + { + fptr = line.FileName + (int)strlen(line.FileName); // remove path + while (*fptr != '\\' && *fptr != '/') + fptr--; - fptr++; + fptr++; - Debugprintf("In Procedure %s - %s Line %d Addr %p\r\n", symbol->Name, fptr, line.LineNumber, symbol->Address ); + Debugprintf("In Procedure %s - %s Line %d Addr %p\r\n", symbol->Name, fptr, line.LineNumber, symbol->Address ); + } + printStack(); + CloseDebugLog(); + + MessageBox(NULL,"Program Error - program closing. See Debug Log for details","BPQ32",MB_ICONSTOP); RealCloseAllPrograms(); Sleep(1000); - CloseDebugLog(); + exit(0); } @@ -195,10 +212,6 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi SymSetOptions(SYMOPT_LOAD_LINES); SymInitialize( process, NULL, TRUE ); - symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 ); - symbol->MaxNameLen = 255; - symbol->SizeOfStruct = sizeof( SYMBOL_INFO ); - AddVectoredExceptionHandler(1, UnhandledExcepFilter); if (_stricmp(lpCmdLine, "Wait") == 0) // If AutoRestart then Delay 5 Secs diff --git a/BPQWinAPP.vcproj b/BPQWinAPP.vcproj index 06a0744..6c69913 100644 --- a/BPQWinAPP.vcproj +++ b/BPQWinAPP.vcproj @@ -2,7 +2,7 @@ @@ -143,8 +143,8 @@ /> + + + + + + + Debug + Win32 + + + Release + Win32 + + + + 18.0 + BPQ32.EXE + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B81} + BPQWinAPP + 10.0 + + + + Application + v145 + false + + + Application + v145 + false + + + + + + + + + + + + + + + <_ProjectFileVersion>18.0.12106.202 + + + c:\DevProgs\BPQ32VS2026\ + C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(ProjectName)\$(Configuration)\ + false + + + C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(ProjectName)\$(Configuration)\ + C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(ProjectName)\$(Configuration)\ + true + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Debug/BPQWinAPP.tlb + + + + Disabled + C:\Users\johnw\OneDrive\Dev\Source\bpq32\Commonsource;C:\Users\johnw\OneDrive\Dev\Source\bpq32\CInclude;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + MultiThreadedDebug + .\Debug/BPQWinAPP.pch + $(IntDir) + $(IntDir) + $(IntDir) + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x0809 + + + Win32bits\bpq32.lib;DbgHelp.lib;%(AdditionalDependencies) + c:\DevProgs\BPQ32VS2026\bpq32.exe + true + true + .\Debug/bpq32.pdb + true + Windows + 0 + 0 + MachineX86 + + + true + .\Debug/BPQWinAPP.bsc + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release/BPQWinAPP.tlb + + + + MinSpace + Default + C:\Users\johnw\OneDrive\Dev\Source\bpq32\Commonsource;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + MultiThreaded + true + C:\msdev2005\Intermed\Release/BPQWinAPP.pch + $(IntDir) + $(IntDir) + $(IntDir) + Level3 + true + EditAndContinue + + + NDEBUG;%(PreprocessorDefinitions) + 0x0809 + + + Win32bits\bpq32.lib;DbgHelp.lib;%(AdditionalDependencies) + c:\DevProgs\bpq32\bpq32.exe + true + true + c:\DevProgs\bpq32\bpq32app.pdb + true + c:\DevProgs\bpq32\bpq32app.map + Windows + MachineX86 + + + true + .\Release/BPQWinAPP.bsc + + + + + Disabled + + + + + + + + + \ No newline at end of file diff --git a/BUILDING.md b/BUILDING.md new file mode 100644 index 0000000..4c6b206 --- /dev/null +++ b/BUILDING.md @@ -0,0 +1,86 @@ + + + + + + +Building LinBPQ from source + + + +BPQ Home   BPQ32 Home + +

Building LinBPQ from source.

+ +

+I provide binaries for Linux on 32 and 64 bit ARM and Intel x86 processors but if you want to run on other Unix like operating systems you can build it from source. You will need to install some dependencies and download the source. The instructions below are for a Debian like system using apt as its package manager - you may need to alter the command for other systems. +

+To download dependencies run: +
+

sudo apt install build-essential git libminiupnpc-dev libconfig-dev libpcap-dev zlib1g-dev  libcap2-bin libjansson-dev libpaho-mqtt-dev libbacktrace-dev
+
+

+Some distributions may not include libpaho-mqtt-dev and/or libbacktrace-dev. The former is used for the MQTT reporting interface. If you don't need that you can build without MQTT support. If you do you can build libpaho-mqtt-dev from source: +

+sudo apt install cmake
+git clone https://github.com/eclipse/paho.mqtt.c.git
+cd paho.mqtt.c
+cmake -Bbuild -H. -DPAHO_ENABLE_TESTING=OFF -DPAHO_BUILD_STATIC=ON -DPAHO_WITH_SSL=OFF -DPAHO_HIGH_PERFORMANCE=ON -DCMAKE_INSTALL_PREFIX=../install
+cd build
+cmake --build . --target install
+
+You need to copy libpaho-mqtt3a.a to your lib directory.
+The commands below work on my ARM and Intel systems but you may need to change if your lib is in a different place.
+
+sudo cp src/libpaho-mqtt3a.a /usr/lib/arm-linux-gnueabihf 
+or
+sudo cp src/libpaho-mqtt3a.a /usr/lib/i386-linux-gnu/
+

+If libbacktrace isn't available you can build it: +

+git clone https://github.com/ianlancetaylor/libbacktrace.git
+cd libbacktrace 
+mkdir build 
+cd build 
+../configure 
+make
+sudo make install
+

+ +To download the LinBPQ source run: +

+git clone https://github.com/g8bpq/linbpq.git
+cd linbpq
+

+To build with MQTT support enter: +

+make
+
+

+To build without MQTT support enter: +

+make nomqtt
+

+This should create linbpq in the current directory. +

+

+ + +John Wiseman G8BPQ
+April 2025
+Updated September 2026
+ + + \ No newline at end of file diff --git a/Bpq32.c b/Bpq32.c index d7370c1..5652e1f 100644 --- a/Bpq32.c +++ b/Bpq32.c @@ -1340,6 +1340,11 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses // More fixes for timer problem introduced in v33 (38) // Changes to INP3 poison reverse and alias reporting (39) // L4 Connect Ack now sent via routing table (39) +// Debug info is now written to a log file rather than syslog (Linux) or Debugview (Windows) (40) +// Backtrace now includes source file info and is written to Debug log (40) +// Add Telnet Server config option "noWebSocks" to disable use of Websocks for Terminal and Driver windows (41) +// Log outpur from running disconnect script (41) +// Prevent Rigcontrol scan from changing frequency when PTT is active (41) #define CKernel @@ -1723,7 +1728,7 @@ int VECTORLENGTH = sizeof (struct _BPQVECSTRUC); int FirstEntry = 1; BOOL CloseLast = TRUE; // If the user started BPQ32.exe, don't close it when other programs close -BOOL Closing = FALSE; // Set if Close All called - prevents respawning bpq32.exe +extern BOOL Closing = FALSE; // Set if Close All called - prevents respawning bpq32.exe BOOL BPQ32_EXE; // Set if Process is running BPQ32.exe. Not initialised. // Used to Kill surplus BPQ32.exe processes @@ -1841,7 +1846,6 @@ void LoadToolHelperRoutines() { HINSTANCE ExtDriver=0; int err; - char msg[100]; ExtDriver=LoadLibrary("kernel32.dll"); @@ -2125,6 +2129,10 @@ VOID MonitorTimerThread(int x) VOID WritetoTraceSupport(struct TNCINFO * TNC, char * Msg, int Len); +VOID * _Q_REM_NP(VOID *PQ, char * File, int Line); + +#define Q_REM_NP(s) _Q_REM_NP(s, __FILE__, __LINE__) + void Semaphored100msCode() { // code that doesn't need to run every tick - run every 100 mS @@ -2156,9 +2164,9 @@ void Semaphored100msCode() while (WritetoConsoleQ) { - UINT * Buffer = Q_REM(&WritetoConsoleQ); + UINT * Buffer = Q_REM_NP(&WritetoConsoleQ); WritetoConsoleSupport((char *)&Buffer[2]); - RelBuff(Buffer); + free(Buffer); } @@ -2753,9 +2761,6 @@ Tell_Sessions() BOOL APIENTRY DllMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReserved) { - DWORD n; - char buf[350]; - int i; unsigned int ProcessID; @@ -3120,7 +3125,6 @@ SkipInit: { if (PIDArray[i] == ProcessID) { - char Log[80]; hWndArray[i] = 0; DeleteMenu(trayMenu,TRAYBASEID+i,MF_BYCOMMAND); } @@ -3567,8 +3571,6 @@ HANDLE OpenConfigFile(char *fn) UCHAR Value[MAX_PATH]; FILETIME LastWriteTime; SYSTEMTIME Time; - char Msg[256]; - // If no directory, use current if (BPQDirectory[0] == 0) @@ -5546,24 +5548,23 @@ DllExport int APIENTRY WritetoConsole(char * buff) DllExport VOID * APIENTRY GetBuff(); +int C_Q_ADD_NP(VOID *PQ, VOID *PBUFF); + int WritetoConsoleLocal(char * buff) { int len=strlen(buff); UINT * buffptr; - if (Semaphore.Flag == 0) - return WritetoConsoleSupport(buff); - - buffptr = GetBuff(); + buffptr = (UINT *)zalloc(512); if (buffptr == 0) // No buffers, so send direct - return WritetoConsoleSupport(buff); + return 0; if (len > 300) len = 300; memcpy(&buffptr[2], buff, len + 1); - C_Q_ADD(&WritetoConsoleQ, buffptr); + C_Q_ADD_NP(&WritetoConsoleQ, buffptr); return 0; } @@ -6337,7 +6338,6 @@ DllExport BOOL APIENTRY SaveReg(char * KeyIn, HANDLE hFile) { if (len > 76) { - len += sprintf(&RegLine[len], "\\\r\n", RegLine); strcat(RegLine, "\\\r\n"); WriteFile(hFile, RegLine, len, &written, NULL); strcpy(RegLine, " "); diff --git a/CBPQ32.sln b/CBPQ32.sln index eabbb30..d9b2153 100644 --- a/CBPQ32.sln +++ b/CBPQ32.sln @@ -13,36 +13,65 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CBPQ32", "CBPQ32.vcproj", " EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BPQChat", "BPQChat.vcproj", "{2BDD2C8A-2B4A-496C-A2EA-6B49AA0670B1}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BPQTerminal", "BPQTerminal.vcproj", "{04F2B9AD-4369-49EA-82EC-3C701C97C6D8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BPQTermTCP", "BPQTermTCP.vcproj", "{99625C77-CABA-469A-A5A7-ECB4EE354225}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 + Relase Static|Win32 = Relase Static|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B81}.Debug|Win32.ActiveCfg = Debug|Win32 {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B81}.Debug|Win32.Build.0 = Debug|Win32 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B81}.Relase Static|Win32.ActiveCfg = Release|Win32 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B81}.Relase Static|Win32.Build.0 = Release|Win32 {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B81}.Release|Win32.ActiveCfg = Release|Win32 {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B81}.Release|Win32.Build.0 = Release|Win32 {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B82}.Debug|Win32.ActiveCfg = Debug|Win32 {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B82}.Debug|Win32.Build.0 = Debug|Win32 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B82}.Relase Static|Win32.ActiveCfg = Release|Win32 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B82}.Relase Static|Win32.Build.0 = Release|Win32 {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B82}.Release|Win32.ActiveCfg = Release|Win32 {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B82}.Release|Win32.Build.0 = Release|Win32 {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Debug|Win32.ActiveCfg = Debug|Win32 {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Debug|Win32.Build.0 = Debug|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Relase Static|Win32.ActiveCfg = Release|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Relase Static|Win32.Build.0 = Release|Win32 {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Release|Win32.ActiveCfg = Release|Win32 {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Release|Win32.Build.0 = Release|Win32 {3766AA10-C777-4ED8-A83D-F1452DE9B666}.Debug|Win32.ActiveCfg = Debug|Win32 {3766AA10-C777-4ED8-A83D-F1452DE9B666}.Debug|Win32.Build.0 = Debug|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B666}.Relase Static|Win32.ActiveCfg = Release|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B666}.Relase Static|Win32.Build.0 = Release|Win32 {3766AA10-C777-4ED8-A83D-F1452DE9B666}.Release|Win32.ActiveCfg = Release|Win32 {3766AA10-C777-4ED8-A83D-F1452DE9B666}.Release|Win32.Build.0 = Release|Win32 {8EFA1E59-8654-4A23-8102-AA77A074D57C}.Debug|Win32.ActiveCfg = Debug|Win32 {8EFA1E59-8654-4A23-8102-AA77A074D57C}.Debug|Win32.Build.0 = Debug|Win32 + {8EFA1E59-8654-4A23-8102-AA77A074D57C}.Relase Static|Win32.ActiveCfg = Release|Win32 + {8EFA1E59-8654-4A23-8102-AA77A074D57C}.Relase Static|Win32.Build.0 = Release|Win32 {8EFA1E59-8654-4A23-8102-AA77A074D57C}.Release|Win32.ActiveCfg = Release|Win32 {8EFA1E59-8654-4A23-8102-AA77A074D57C}.Release|Win32.Build.0 = Release|Win32 {2BDD2C8A-2B4A-496C-A2EA-6B49AA0670B1}.Debug|Win32.ActiveCfg = Debug|Win32 {2BDD2C8A-2B4A-496C-A2EA-6B49AA0670B1}.Debug|Win32.Build.0 = Debug|Win32 + {2BDD2C8A-2B4A-496C-A2EA-6B49AA0670B1}.Relase Static|Win32.ActiveCfg = Release|Win32 + {2BDD2C8A-2B4A-496C-A2EA-6B49AA0670B1}.Relase Static|Win32.Build.0 = Release|Win32 {2BDD2C8A-2B4A-496C-A2EA-6B49AA0670B1}.Release|Win32.ActiveCfg = Release|Win32 {2BDD2C8A-2B4A-496C-A2EA-6B49AA0670B1}.Release|Win32.Build.0 = Release|Win32 + {04F2B9AD-4369-49EA-82EC-3C701C97C6D8}.Debug|Win32.ActiveCfg = Debug|Win32 + {04F2B9AD-4369-49EA-82EC-3C701C97C6D8}.Debug|Win32.Build.0 = Debug|Win32 + {04F2B9AD-4369-49EA-82EC-3C701C97C6D8}.Relase Static|Win32.ActiveCfg = Relase Static|Win32 + {04F2B9AD-4369-49EA-82EC-3C701C97C6D8}.Relase Static|Win32.Build.0 = Relase Static|Win32 + {04F2B9AD-4369-49EA-82EC-3C701C97C6D8}.Release|Win32.ActiveCfg = Release|Win32 + {04F2B9AD-4369-49EA-82EC-3C701C97C6D8}.Release|Win32.Build.0 = Release|Win32 + {99625C77-CABA-469A-A5A7-ECB4EE354225}.Debug|Win32.ActiveCfg = Debug|Win32 + {99625C77-CABA-469A-A5A7-ECB4EE354225}.Debug|Win32.Build.0 = Debug|Win32 + {99625C77-CABA-469A-A5A7-ECB4EE354225}.Relase Static|Win32.ActiveCfg = Release|Win32 + {99625C77-CABA-469A-A5A7-ECB4EE354225}.Relase Static|Win32.Build.0 = Release|Win32 + {99625C77-CABA-469A-A5A7-ECB4EE354225}.Release|Win32.ActiveCfg = Release|Win32 + {99625C77-CABA-469A-A5A7-ECB4EE354225}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/CBPQ32.vcproj b/CBPQ32.vcproj index e211ac4..6a48af8 100644 --- a/CBPQ32.vcproj +++ b/CBPQ32.vcproj @@ -2,7 +2,7 @@ - + Debug @@ -11,22 +11,24 @@ + 18.0 + BPQ32.DLL {8EFA1E59-8654-4A23-8102-AA77A074D57C} CBPQ32 Win32Proj - 10.0.17763.0 + 10.0 DynamicLibrary - v141 + v145 NotSet false DynamicLibrary - v141 - MultiByte + v145 + NotSet @@ -40,16 +42,17 @@ - <_ProjectFileVersion>15.0.28127.55 + <_ProjectFileVersion>18.0.12106.202 - $(SolutionDir)$(Configuration)\ - C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(Configuration)\ + c:\DevProgs\BPQ32VS2026\ + C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(ProjectName)\$(Configuration)\ true + bpq32 - $(SolutionDir)$(Configuration)\ - C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(Configuration)\ + Win32bits\ + C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(ProjectName)\$(Configuration)\ false @@ -60,8 +63,8 @@ Disabled - ..\CInclude;..\CommonSource;..\CKernel;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;BPQ32_EXPORTS;MDIKERNEL;_USE_32BIT_TIME_T;%(PreprocessorDefinitions) + ..\BPQSource\Win32bits;..\BPQSource;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;BPQ32_EXPORTS;MDIKERNEL;_USE_32BIT_TIME_T;BPQ32;NOMQTT;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebug @@ -74,11 +77,11 @@ /section:_BPQDATA,srw %(AdditionalOptions) - WS2_32.Lib;winmm.lib;DbgHelp.lib;comctl32.lib;Iphlpapi.lib;setupapi.lib;..\lib\libconfig.lib;miniupnpc.lib;zlibstat.lib;%(AdditionalDependencies) - c:\DevProgs\BPQ32\bpq32.dll + WS2_32.Lib;winmm.lib;DbgHelp.lib;comctl32.lib;Iphlpapi.lib;setupapi.lib;C:\OneDrive\Dev\Source\bpq32\libconfig\Release\libconfig.LIB;C:\Users\johnw\Downloads\upnpc-exe-win32-20220515\miniupnpc.lib;zlibstat.lib;%(AdditionalDependencies) + c:\DevProgs\BPQ32VS2026\bpq32.dll false LIBCMTD.lib;%(IgnoreSpecificDefaultLibraries) - ..\CommonSource\bpq32.def + ..\BPQSource\bpq32.def true true c:\DevProgs\BPQ32\bpqdev.map @@ -89,7 +92,7 @@ false 0x42000000 - ..\lib\bpq32.lib + Win32bits\bpq32.lib MachineX86 false @@ -114,8 +117,8 @@ /D "MDIKERNEL" %(AdditionalOptions) Disabled false - ..\CInclude;..\CommonSource;..\CKernel;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;BPQ32_EXPORTS;MDIKERNEL;_USE_32BIT_TIME_T;%(PreprocessorDefinitions) + ..\BPQSource\Win32bits;..\BPQSource;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;BPQ32_EXPORTS;MDIKERNEL;_USE_32BIT_TIME_T;NOMQTT;%(PreprocessorDefinitions) MultiThreaded All @@ -125,9 +128,9 @@ /section:_BPQDATA,srw %(AdditionalOptions) - WS2_32.Lib;winmm.lib;DbgHelp.lib;comctl32.lib;setupapi.lib;..\lib\libconfig.lib;miniupnpc.lib;zlibstat.lib;%(AdditionalDependencies) - C:\DevProgs\BPQ32\bpq32.dll - ..\CommonSource\bpq32.def + WS2_32.Lib;winmm.lib;comctl32.lib;setupapi.lib;Win32bits\libconfig.lib;miniupnpc.lib;zlibstat.lib;DbgHelp.lib;%(AdditionalDependencies) + c:\DevProgs\BPQ32\bpq32.dll + ..\BPQSource\bpq32.def true c:\DevProgs\BPQ32\bpq32.pdb true @@ -149,14 +152,17 @@ + + + @@ -167,14 +173,23 @@ - - + + + + + + + + + + + @@ -189,8 +204,29 @@ + + CompileAsC + + + + + + + + + + + + + + + + + + + @@ -214,7 +250,7 @@ - + diff --git a/CBPQ322026.sln b/CBPQ322026.sln new file mode 100644 index 0000000..ad64694 --- /dev/null +++ b/CBPQ322026.sln @@ -0,0 +1,84 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 18 +VisualStudioVersion = 18.10.12201.205 stable +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BPQ32.EXE", "BPQWinAPP.vcxproj", "{005A91EA-3A00-4FB4-ADD9-EB78DBFA2B81}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinmorControl", "WinmorControl.vcxproj", "{005A91EA-3A00-4FB4-ADD9-EB78DBFA2B82}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BPQMail", "BPQMail.vcxproj", "{3766AA10-C777-4ED8-A83D-F1452DE9B665}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LinBPQ", "MailNode.vcxproj", "{3766AA10-C777-4ED8-A83D-F1452DE9B666}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BPQ32.DLL", "CBPQ32.vcxproj", "{8EFA1E59-8654-4A23-8102-AA77A074D57C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BPQChat", "BPQChat.vcxproj", "{2BDD2C8A-2B4A-496C-A2EA-6B49AA0670B1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BPQTerminal", "BPQTerminal.vcxproj", "{04F2B9AD-4369-49EA-82EC-3C701C97C6D8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BPQTermTCP", "BPQTermTCP.vcxproj", "{99625C77-CABA-469A-A5A7-ECB4EE354225}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Relase Static|Win32 = Relase Static|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B81}.Debug|Win32.ActiveCfg = Debug|Win32 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B81}.Debug|Win32.Build.0 = Debug|Win32 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B81}.Relase Static|Win32.ActiveCfg = Release|Win32 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B81}.Relase Static|Win32.Build.0 = Release|Win32 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B81}.Release|Win32.ActiveCfg = Release|Win32 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B81}.Release|Win32.Build.0 = Release|Win32 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B82}.Debug|Win32.ActiveCfg = Debug|Win32 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B82}.Debug|Win32.Build.0 = Debug|Win32 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B82}.Relase Static|Win32.ActiveCfg = Release|Win32 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B82}.Relase Static|Win32.Build.0 = Release|Win32 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B82}.Release|Win32.ActiveCfg = Release|Win32 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B82}.Release|Win32.Build.0 = Release|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Debug|Win32.ActiveCfg = Debug|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Debug|Win32.Build.0 = Debug|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Relase Static|Win32.ActiveCfg = Release|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Relase Static|Win32.Build.0 = Release|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Release|Win32.ActiveCfg = Release|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B665}.Release|Win32.Build.0 = Release|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B666}.Debug|Win32.ActiveCfg = Debug|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B666}.Debug|Win32.Build.0 = Debug|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B666}.Relase Static|Win32.ActiveCfg = Release|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B666}.Relase Static|Win32.Build.0 = Release|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B666}.Release|Win32.ActiveCfg = Release|Win32 + {3766AA10-C777-4ED8-A83D-F1452DE9B666}.Release|Win32.Build.0 = Release|Win32 + {8EFA1E59-8654-4A23-8102-AA77A074D57C}.Debug|Win32.ActiveCfg = Debug|Win32 + {8EFA1E59-8654-4A23-8102-AA77A074D57C}.Debug|Win32.Build.0 = Debug|Win32 + {8EFA1E59-8654-4A23-8102-AA77A074D57C}.Relase Static|Win32.ActiveCfg = Release|Win32 + {8EFA1E59-8654-4A23-8102-AA77A074D57C}.Relase Static|Win32.Build.0 = Release|Win32 + {8EFA1E59-8654-4A23-8102-AA77A074D57C}.Release|Win32.ActiveCfg = Release|Win32 + {8EFA1E59-8654-4A23-8102-AA77A074D57C}.Release|Win32.Build.0 = Release|Win32 + {2BDD2C8A-2B4A-496C-A2EA-6B49AA0670B1}.Debug|Win32.ActiveCfg = Debug|Win32 + {2BDD2C8A-2B4A-496C-A2EA-6B49AA0670B1}.Debug|Win32.Build.0 = Debug|Win32 + {2BDD2C8A-2B4A-496C-A2EA-6B49AA0670B1}.Relase Static|Win32.ActiveCfg = Release|Win32 + {2BDD2C8A-2B4A-496C-A2EA-6B49AA0670B1}.Relase Static|Win32.Build.0 = Release|Win32 + {2BDD2C8A-2B4A-496C-A2EA-6B49AA0670B1}.Release|Win32.ActiveCfg = Release|Win32 + {2BDD2C8A-2B4A-496C-A2EA-6B49AA0670B1}.Release|Win32.Build.0 = Release|Win32 + {04F2B9AD-4369-49EA-82EC-3C701C97C6D8}.Debug|Win32.ActiveCfg = Debug|Win32 + {04F2B9AD-4369-49EA-82EC-3C701C97C6D8}.Debug|Win32.Build.0 = Debug|Win32 + {04F2B9AD-4369-49EA-82EC-3C701C97C6D8}.Relase Static|Win32.ActiveCfg = Relase Static|Win32 + {04F2B9AD-4369-49EA-82EC-3C701C97C6D8}.Relase Static|Win32.Build.0 = Relase Static|Win32 + {04F2B9AD-4369-49EA-82EC-3C701C97C6D8}.Release|Win32.ActiveCfg = Release|Win32 + {04F2B9AD-4369-49EA-82EC-3C701C97C6D8}.Release|Win32.Build.0 = Release|Win32 + {99625C77-CABA-469A-A5A7-ECB4EE354225}.Debug|Win32.ActiveCfg = Debug|Win32 + {99625C77-CABA-469A-A5A7-ECB4EE354225}.Debug|Win32.Build.0 = Debug|Win32 + {99625C77-CABA-469A-A5A7-ECB4EE354225}.Relase Static|Win32.ActiveCfg = Release|Win32 + {99625C77-CABA-469A-A5A7-ECB4EE354225}.Relase Static|Win32.Build.0 = Release|Win32 + {99625C77-CABA-469A-A5A7-ECB4EE354225}.Release|Win32.ActiveCfg = Release|Win32 + {99625C77-CABA-469A-A5A7-ECB4EE354225}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FB815A29-A2DD-470A-B0AF-7188AA0F4C7F} + EndGlobalSection +EndGlobal diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..9dcfb88 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.18) + +project(LinBPQ) + +# Our Project + +set(CMAKE_C_FLAGS "-DLINBPQ -g -fcommon -fasynchronous-unwind-tables") + +set(SOURCE_FILES +pngwtran.c pngrtran.c pngset.c pngrio.c pngwio.c pngtrans.c pngrutil.c pngwutil.c + pngread.c pngwrite.c png.c pngerror.c pngget.c pngmem.c APRSIconData.c AISCommon.c + upnp.c APRSStdPages.c HSMODEM.c WinRPR.c KISSHF.c TNCEmulators.c bpqhdlc.c SerialPort.c + adif.c WebMail.c utf8Routines.c VARA.c LzFind.c Alloc.c LzmaDec.c LzmaEnc.c LzmaLib.c + Multicast.c ARDOP.c IPCode.c FLDigi.c linether.c CMSAuth.c APRSCode.c BPQtoAGW.c KAMPactor.c + AEAPactor.c HALDriver.c MULTIPSK.c BBSHTMLConfig.c ChatHTMLConfig.c BBSUtilities.c bpqaxip.c + BPQINP3.c BPQNRR.c cMain.c Cmd.c CommonCode.c HTMLCommonCode.c compatbits.c config.c datadefs.c + FBBRoutines.c HFCommon.c Housekeeping.c HTTPcode.c kiss.c L2Code.c L3Code.c L4Code.c lzhuf32.c + MailCommands.c MailDataDefs.c LinBPQ.c MailRouting.c MailTCP.c MBLRoutines.c md5.c Moncode.c + NNTPRoutines.c RigControl.c TelnetV6.c WINMOR.c TNCCode.c UZ7HODrv.c WPRoutines.c + SCSTrackeMulti.c SCSPactor.c SCSTracker.c HanksRT.c UIRoutines.c AGWAPI.c AGWMoncode.c + DRATS.c FreeDATA.c base64.c Events.c nodeapi.c mailapi.c mqtt.c RHP.c NETROMTCP.c) + +add_executable(${PROJECT_NAME} ${SOURCE_FILES}) + diff --git a/Cmd.c b/Cmd.c index b7faab9..a4d8c02 100644 --- a/Cmd.c +++ b/Cmd.c @@ -4326,6 +4326,45 @@ VOID NRRCMD(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct C return; } +VOID SendNRPing(struct DEST_LIST * DEST, TRANSPORTENTRY * Session); + +VOID NRPING(TRANSPORTENTRY * Session, char * Bufferptr, char * CmdTail, struct CMDX * UserCMD) +{ + // Send Paula's NCMP PING command = Netrom Ping + + char * ptr, *Context; + struct DEST_LIST * Dest = DESTS; + int count = MAXDESTS; + + ptr = strtok_s(CmdTail, " ", &Context); + + if (ptr) + { + UCHAR AXCall[8]; + int count; + + ConvToAX25(ptr, AXCall); + strcat(ptr, " "); + + for (count = 0; count < MAXDESTS; count++) + { + if (memcmp(Dest->DEST_ALIAS, ptr, 6) == 0 || CompareCalls(Dest->DEST_CALL, AXCall)) + { + SendNRPing(Dest, Session); + memcpy(Bufferptr, OKMSG, 3); + Bufferptr += 3; + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); + + return; + } + Dest++; + } + } + Bufferptr = Cmdprintf(Session, Bufferptr, "Not found\r"); + SendCommandReply(Session, REPLYBUFFER, (int)(Bufferptr - (char *)REPLYBUFFER)); + return; +} + int CHECKINTERLOCK(struct PORTCONTROL * OURPORT) { // See if any Interlocked ports are Busy @@ -4884,6 +4923,7 @@ struct CMDX COMMANDS[] = "AXMHEARD ",3,AXMHEARD,0, "TELSTATUS ",3,SHOWTELNET,0, "NRR ",1,NRRCMD,0, + "NPING ",1,NRPING,0, "PING ",2,PING,0, "AGWSTATUS ",3,SHOWAGW,0, "ARP ",3,SHOWARP,0, diff --git a/CommonCode.c b/CommonCode.c index 2708e79..3559135 100644 --- a/CommonCode.c +++ b/CommonCode.c @@ -3829,6 +3829,7 @@ int __sync_lock_test_and_set(int * ptr, int val) #define GetSemaphore(Semaphore,ID) _GetSemaphore(Semaphore, ID, __FILE__, __LINE__) +BOOL Closing; void _GetSemaphore(struct SEM * Semaphore, int ID, char * File, int Line) { @@ -3843,7 +3844,7 @@ void _GetSemaphore(struct SEM * Semaphore, int ID, char * File, int Line) loop1: - while (Semaphore->Flag != 0) + while (Semaphore->Flag != 0 && Closing == 0) { Sleep(10); } @@ -3904,41 +3905,54 @@ USHORT WINAPI RtlCaptureStackBackTrace( */ #endif -void printStack(void) +void printStack() { -#ifdef WIN32 -#ifdef _DEBUG // So we can use on 98/2K - - unsigned int i; - void * stack[ 100 ]; +#ifdef BPQ32 + unsigned int i, n; + void * stack[ 100 ]; unsigned short frames; - SYMBOL_INFO * symbol; - HANDLE process; - Debugprintf("Stack Backtrace"); + DWORD dwDisplacement; + IMAGEHLP_LINE64 line; + char * fptr; + HANDLE process; + + + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; + + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol->MaxNameLen = MAX_SYM_NAME; + + Debugprintf("Stack Backtrace\r\n"); process = GetCurrentProcess(); + SymSetOptions(SYMOPT_LOAD_LINES); SymInitialize( process, NULL, TRUE ); - frames = RtlCaptureStackBackTrace( 0, 60, stack, NULL ); - symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 ); - symbol->MaxNameLen = 255; - symbol->SizeOfStruct = sizeof( SYMBOL_INFO ); + frames = RtlCaptureStackBackTrace(0, 60, stack, NULL ); for( i = 0; i < frames; i++ ) { - SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol ); + n = SymGetLineFromAddr64(process, (DWORD64)stack[i], &dwDisplacement, &line); + n = SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol ); - Debugprintf( "%i: %s - %p", frames - i - 1, symbol->Name, symbol->Address ); - } + if (line.FileName) + { + fptr = line.FileName + (int)strlen(line.FileName); // remove path + while (*fptr != '\\' && *fptr != '/') + fptr--; - free(symbol); + fptr++; -#endif + Debugprintf("%i: %s - %s Line %d Addr %p", frames - i - 1, symbol->Name, fptr, line.LineNumber, symbol->Address ); + } + } #endif } + pthread_t ResolveUpdateThreadId = 0; char NodeMapServer[80] = "update.g8bpq.net"; diff --git a/DragSize.cur b/DragSize.cur new file mode 100644 index 0000000..a33158a Binary files /dev/null and b/DragSize.cur differ diff --git a/HTTPcode.c b/HTTPcode.c index 4068a48..1a50fed 100644 --- a/HTTPcode.c +++ b/HTTPcode.c @@ -885,7 +885,7 @@ VOID HTTPTimer() OutBuffer = &Msg[0]; } - // If secure session enable an hidden controls + // If secure session enable any hidden controls if (sock->WebSecure) { @@ -2026,7 +2026,7 @@ int InnerProcessHTTPMessage(struct ConnectionInfo * conn) strcpy(URL, MsgPtr); - WebSock = strstr(MsgPtr, "Upgrade: websocket"); + WebSock = stristr(MsgPtr, "Upgrade: websocket"); encPtr = stristr(MsgPtr, "Accept-Encoding:"); @@ -2035,7 +2035,7 @@ int InnerProcessHTTPMessage(struct ConnectionInfo * conn) else Encoding[0] = 0; - ptr = strstr(MsgPtr, "BPQSessionCookie=N"); + ptr = stristr(MsgPtr, "BPQSessionCookie=N"); if (ptr) { @@ -2080,7 +2080,7 @@ int InnerProcessHTTPMessage(struct ConnectionInfo * conn) // "Sec-WebSocket-Protocol: chat\r\n" "\r\n"; - ptr = strstr(MsgPtr, "Sec-WebSocket-Key:"); + ptr = stristr(MsgPtr, "Sec-WebSocket-Key:"); if (ptr) { @@ -3398,18 +3398,18 @@ doHeader: " if (\"WebSocket\" in window)" " {" " // Let us open a web socket. Get address from URL\r\n" - + " var proto = (window.location.protocol === 'https:') ? 'wss://' : 'ws://';\r\n" " ws = new WebSocket(proto + window.location.host + '/RIGCTL');\r\n" - + " ws.onopen = function() {\r\n" - + " // Web Socket is connected\r\n" " const div = document.getElementById('div');\r\n" " div.innerHTML = 'Websock Connected'\r\n" " };\r\n" - + " ws.onmessage = function (evt)" " {" " var received_msg = evt.data;\r\n" @@ -3442,7 +3442,7 @@ doHeader: "
Waiting for data...
\r\n" "\r\n"; - + char NoRigCtl[] = "\r\n" "Rigcontrol\r\n" @@ -3459,72 +3459,87 @@ doHeader: else if (_stricmp(NodeURL, "/Node/DevicePage") == 0) { - char Part1[] = - "\r\n" - "Device\r\n" - "\r\n" - "\r\n" - "\r\n" - "
Waiting for data...
\r\n" - "\r\n"; + if (TCP->noWebSocks == 0) + { + char Part1[] = + "\r\n" + "Device\r\n" + "\r\n" + "\r\n" + "\r\n" + "
Waiting for data...
\r\n" + "\r\n"; + + int Port = atoi(Context); + int xxx; + + ReplyLen = sprintf(_REPLYBUFFER, Part1, Port, Port, Port); + xxx = ReplyLen; + } + else + { + int port = atoi(Context); - int Port = atoi(Context); - int xxx; + if (port > 0 && port <= MaxBPQPortNo) + { + struct TNCINFO * TNC = TNCInfo[port]; - ReplyLen = sprintf(_REPLYBUFFER, Part1, Port, Port, Port); - xxx = ReplyLen; + if (TNC && TNC->WebWindowProc) + ReplyLen = TNC->WebWindowProc(TNC, _REPLYBUFFER, LOCAL); + } + } } else if (_stricmp(NodeURL, "/Node/ShowLog.html") == 0) @@ -4550,7 +4565,12 @@ CMDS60: }}} */ - else if (_stricmp(NodeURL, "/Node/Terminal.html") == 0) + else if (_stricmp(NodeURL, "/Node/WebSockTerm.html") == 0 && TCP->noWebSocks == 0) + { + ReplyLen = DoWebSockTerm(Session, conn, _REPLYBUFFER, LOCAL, COOKIE, Context, sock); + } + + else if (_stricmp(NodeURL, "/Node/Terminal.html" ) == 0 || (_stricmp(NodeURL, "/Node/WebSockTerm.html") == 0 && TCP->noWebSocks)) { if (COOKIE && Session) { @@ -4604,11 +4624,6 @@ CMDS60: ReplyLen = sprintf(_REPLYBUFFER, TermSignon, Mycall, Mycall, Context, ""); } - else if (_stricmp(NodeURL, "/Node/WebSockTerm.html") == 0) - { - ReplyLen = DoWebSockTerm(Session, conn, _REPLYBUFFER, LOCAL, COOKIE, Context, sock); - } - else if (_stricmp(NodeURL, "/Node/Signon.html") == 0) { ReplyLen = sprintf(_REPLYBUFFER, NodeSignon, Mycall, Mycall, Context); @@ -6150,6 +6165,8 @@ int DoWebSockTerm(struct HTTPConnectionInfo * Session, struct ConnectionInfo * c " var proto = (window.location.protocol === 'https:') ? 'wss://' : 'ws://';\r\n" " ws = new WebSocket(proto + window.location.host + '/WEBTERM?%s&%s&%s&%d');\r\n" +// " alert(window.location.href);" +// " alert(proto + window.location.host);" " ws.onopen = function() // Web Socket is connected\r\n" " {\r\n" " const div = document.getElementById('div');\r\n" diff --git a/L4Code.c b/L4Code.c index a77b24d..76f66de 100644 --- a/L4Code.c +++ b/L4Code.c @@ -99,13 +99,43 @@ int sessionStatusInterval = 300; // 5 mins extern APPLCALLS * APPL; +void SendNCMPDestunreachable(L3MESSAGEBUFFER * L3MSG, int Code) +{ + // Return NCMP Dest Unreachable TTL Exceeded + + struct DEST_LIST * DEST = 0; + + UCHAR ORIG[28]; + + memcpy(ORIG, L3MSG->L3SRCE, 28); // First 28 bytes of unrouteable message + L3MSG->L3TTL = L3LIVES; + L3MSG->LENGTH = MSGHDDRLEN + 21 + 28; // Include PID 20 L3/4 Header 28 Orig Datagram + memcpy(L3MSG->L3DEST, L3MSG->L3SRCE, 7); + memcpy(L3MSG->L3SRCE, MYCALL, 7); + L3MSG->L4INDEX = 0x0f; + L3MSG->L4ID = 0x00; + L3MSG->L4TXNO = 5; // Unreachable + L3MSG->L4RXNO = Code; + L3MSG->L4FLAGS = 0; + memcpy(L3MSG->L4DATA, ORIG, 28); // PID + L3 Header + + if (FindDestination(L3MSG->L3DEST, &DEST)) + { + C_Q_ADD(&DEST->DEST_Q, (UINT *)L3MSG); + return; + } + + ReleaseBuffer(L3MSG); + return; +} + + VOID NETROMMSG(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG) { // MAKE SURE PID IS 0CF - IN CASE SOMEONE IS SENDING L2 STUFF ON WHAT // WE THINK IS A _NODE-_NODE LINK - struct DEST_LIST * DEST; - + struct DEST_LIST * DEST = 0; int n; if (L3MSG->L3PID != 0xCF) @@ -188,7 +218,9 @@ VOID NETROMMSG(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG) if (L3MSG->L3TTL == 0) { - ReleaseBuffer(L3MSG); + // Return NCMP Dest Unreachable TTL Exceeded (5) + + SendNCMPDestunreachable(L3MSG, 5); return; } @@ -226,10 +258,14 @@ VOID NETROMMSG(struct _LINKTABLE * LINK, L3MESSAGEBUFFER * L3MSG) if (FindDestination(L3MSG->L3DEST, &DEST) == 0) { - ReleaseBuffer(L3MSG); // CANT FIND DESTINATION + // Return NCMP Dest Unreachable Host Ubknown (0) + + SendNCMPDestunreachable(L3MSG, 0); return; } + + // IF MESSAGE ORIGINTED HERE, THERE MUST BE A ROUTING LOOP - // THERE IS LITTLE POINT SENDING IT OVER THE SAME ROUTE AGAIN, // SO SET ANOTHER ROUTE ACTIVE IF POSSIBLE @@ -2862,13 +2898,214 @@ Type Purpose 4 Routing Information Unicast 5 Destination Unreachable + 0 Host Unknown The router does not know the destination + node. + + 1 Host Unreachable The destination node is known, but there + are no viable routes at this time, due to +obsolescence or link failure. + 2 Net Unreachable The number of hops to the target system is + more than the remaining Time To Live. + 3 Proto Unreachable The destination host does not know how to + handle the requested protocol. + + 4 Service Unreach The requested service is not implemented at + the destination host. + + 5 TTL Exceeded The datagram could not be routed any + further because the Layer 3 Time to Live +has reached zero. + + 6 Frag Required The datagram is too large for the outgoing + link, and the link does not support +fragmentation. + 7 Source Quench The datagram could not be handled at this + time due to insufficient resources. This +situation is temporary. Upon receipt of +this message, the sender should reduce the +sending rate. */ +char NCMPTypes[6][28] = { + "Probe Request", + "Probe Reply", + "Echo Request", + "Echo Reply", + "Routing Information Unicast", + "Destination Unreachable"}; + +char Reasons[8][24] = { + "Host Unknown", + "Host Unreachable", + "Net Unreachable", + "Proto Unreachabl", + "Service Unreachable", + "TTL Exceeded", + "Fragmentation Required", + "Source Quench"}; + void ProcessNCMPMsg(L3MESSAGEBUFFER * L3MSG) { + struct DEST_LIST * DEST; + L3MESSAGEBUFFER OLDMSG; + TRANSPORTENTRY * L4; + TRANSPORTENTRY * Partner; + char Nodename[20]; + int n; + struct DATAMESSAGE * Msg; + UCHAR * ptr1; + uint16_t NOW = (uint16_t)GetTickCount() & 0xffff; + uint16_t RTT; + int Hops; + switch(L3MSG->L4TXNO & 15) { case 0: + + n = 1; + break; + + case 1: + + n = 1; + break; + + case 2: // Echo + + // Return an Echo Response + + L3MSG->L4TXNO = 3; + + L3SWAPADDRESSES(L3MSG); + + // L3RXNO has originator's TTL + + // We return the TTL from the originating message in L3RXNO + + L3MSG->L4RXNO = L3MSG->L3TTL; + + L3MSG->L3TTL = L3LIVES; + + if (FindDestination(L3MSG->L3DEST, &DEST)) + { + C_Q_ADD(&DEST->DEST_Q, (UINT *)L3MSG); + return; + } + break; + + case 3: // Echo Reply + + RTT = NOW - ((L3MSG->L4DATA[2] << 8) + L3MSG->L4DATA[3]); + Hops = L3LIVES + 1 - L3MSG->L4RXNO; + + L4 = L4TABLE + (L3MSG->L4DATA[0] << + 8) + L3MSG->L4DATA[1]; + + Nodename[DecodeNodeName(L3MSG->L3SRCE, Nodename)] = 0; // null terminate + + Msg = (PDATAMESSAGE)L3MSG; // reuse input buffer + + Msg->PID = 0xf0; + ptr1 = SetupNodeHeader(Msg); + + ptr1 += sprintf(ptr1, "Echo reply from %s: rtt %d msec, %d hop(s)\r", Nodename, RTT, Hops); + + Msg->LENGTH = (int)(ptr1 - (UCHAR *)Msg); + + C_Q_ADD(&L4->L4TX_Q, Msg); + + PostDataAvailable(L4); + return; + + + case 4: // Routing info + + break; + + case 5: // Destination Unreachable + + // Most useful in response to a connect request to tell user of a problem + // Maybe also on an established session, perhaps to select another route or tell user + + // Pick out the unrouted datagram (in the INFO field) Should be 28 bytes. Use an L3MESSAGEBUFFER struct + + memcpy(OLDMSG.L3SRCE, L3MSG->L4DATA, 28); + + // if the original message is an NCMP Probe or Echo, processs Unreachables + + if (OLDMSG.L4INDEX == 15 && OLDMSG.L4ID ==0 && OLDMSG.L4TXNO == 2) + { + // Process like Ping Response but with different message + + L4 = L4TABLE + (OLDMSG.L4DATA[0] << + 8) + OLDMSG.L4DATA[1]; + + Nodename[DecodeNodeName(L3MSG->L3SRCE, Nodename)] = 0; // null terminate + + Msg = (PDATAMESSAGE)L3MSG; // reuse input buffer + + Msg->PID = 0xf0; + ptr1 = SetupNodeHeader(Msg); + + ptr1 += sprintf(ptr1, "Destination Unreachable(%s) returned from %s to Echo Request\r", Reasons[L3MSG->L4RXNO], Nodename); + + Msg->LENGTH = (int)(ptr1 - (UCHAR *)Msg); + + C_Q_ADD(&L4->L4TX_Q, Msg); + + PostDataAvailable(L4); + return; + } + // Find the connection + + n = MAXCIRCUITS; + L4 = L4TABLE; + + while (n--) + { + // if ((L4->L4USER[0] && L4->FARID == OLDMSG.L4RXNO && L4->FARINDEX == OLDMSG.L4TXNO) || // Paula returns session in RX/TXNO, I sent in ID/INDEX + if (L4->L4USER[0] && L4->CIRCUITID == OLDMSG.L4ID && L4->CIRCUITINDEX == OLDMSG.L4INDEX) + { + // Check calls as well + + if (memcmp(L4->L4TARGET.DEST->DEST_CALL, &OLDMSG.L3DEST, 7) == 0) + { + if ((OLDMSG.L4FLAGS & 15) != L4CREQ) // for now only on Connect Request + { + ReleaseBuffer(L3MSG); + return; + } + + Partner = L4->L4CROSSLINK; + DEST = L4->L4TARGET.DEST; + + CLEARSESSIONENTRY(L4); + + if (Partner) + Partner->L4CROSSLINK = NULL; // CLEAR CROSSLINK + + if (Partner == 0) + { + ReleaseBuffer(L3MSG); + return; + } + + Nodename[DecodeNodeName(L3MSG->L3SRCE, Nodename)] = 0; // null terminate + + Msg = (PDATAMESSAGE)L3MSG; // reuse input buffer + + Msg->PID = 0xf0; + ptr1 = SetupNodeHeader(Msg); + ptr1 += sprintf(ptr1, "Destination Unreachable(%s) from %s\r", Reasons[L3MSG->L4RXNO], Nodename); + + Msg->LENGTH = (int)(ptr1 - (UCHAR *)Msg); + + C_Q_ADD(&Partner->L4TX_Q, Msg); + + PostDataAvailable(Partner); + return; + } + } + L4++; + } break; } @@ -2876,3 +3113,50 @@ void ProcessNCMPMsg(L3MESSAGEBUFFER * L3MSG) return; } +VOID SendNRPing(struct DEST_LIST * DEST, TRANSPORTENTRY * Session) +{ + L3MESSAGEBUFFER * Msg = GetBuff(); + int SessID; + uint16_t NOW = (uint16_t)GetTickCount() & 0xffff; + + if (Msg == NULL) + return; + + SessID = (Session - L4TABLE); // Save Session Pointer for reply + + Msg->Port = 0; + Msg->L3PID = NRPID; + + memcpy(Msg->L3DEST, DEST->DEST_CALL, 7); + memcpy(Msg->L3SRCE, MYCALL, 7); +/* + ----------------------------------------------------------- + | 0F | 00 | Type=2 | TTL | 00 | ID | Seq | Optional payload | + ----------------------------------------------------------- + "TTL" is the initial Layer 3 TTL + "ID" is a unique 16 bit identifier, sent high octet first, + allowing the originator to match responses with the requests. + "Seq" is a 16 bit sequence number, sent high octet first. + Usually carries a timestamp, allowing the RTT to be computed. + if (L3MSG->L4ID == 0x00 && L3MSG->L4INDEX == 0x0f) // Paula's NCMP + +*/ + + Msg->L3TTL = L3LIVES; + Msg->L4INDEX = 0x0f; + Msg->L4ID = 0; + Msg->L4TXNO = 2; + Msg->L4RXNO = L3LIVES; + Msg->L4FLAGS = 0; + Msg->L4DATA[0] = SessID >> 8; + Msg->L4DATA[1] = SessID & 0xff; + Msg->L4DATA[2] = NOW >> 8; + Msg->L4DATA[3] = NOW & 0xff; + + Msg->LENGTH = 25 + MSGHDDRLEN; + + C_Q_ADD(&DEST->DEST_Q, Msg); +} + + + diff --git a/LinBPQ.c b/LinBPQ.c index 9734abd..8515119 100644 --- a/LinBPQ.c +++ b/LinBPQ.c @@ -1153,7 +1153,73 @@ void UnSemaphored100msCode() Slowtimer = 0; } -#ifndef WIN32 +#ifdef WIN32 + +#include "DbgHelp.h" + +HANDLE process; + + + + +int inErrorhandling = 0; + +LONG WINAPI UnhandledExcepFilter(PEXCEPTION_POINTERS pExcepPointers) +{ + DWORD dwDisplacement; + IMAGEHLP_LINE64 line; + char * fptr; + + + time_t T; + struct tm * tm; + + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; + + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol->MaxNameLen = MAX_SYM_NAME; + + + T = time(NULL); + tm = gmtime(&T); + + if (inErrorhandling) + { + MessageBox(NULL,"Program Error in error handler - program closing. See Debug Log for details","BPQ32",MB_ICONSTOP); + + exit(0); + } + + inErrorhandling = 1; + + if(pExcepPointers->ExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_C) + return EXCEPTION_CONTINUE_EXECUTION; + + SymFromAddr( process, ((DWORD)pExcepPointers->ExceptionRecord->ExceptionAddress), 0, symbol ); + + Debugprintf("\r\n\r\nProgram error trapped at %02d:%02d:%02d\r\n", tm->tm_hour, tm->tm_min, tm->tm_sec); + + SymGetLineFromAddr64(process, (DWORD)pExcepPointers->ExceptionRecord->ExceptionAddress, &dwDisplacement, &line); + + if (line.FileName) + { + fptr = line.FileName + (int)strlen(line.FileName); // remove path + while (*fptr != '\\' && *fptr != '/') + fptr--; + + fptr++; + + Debugprintf("In Procedure %s - %s Line %d Addr %p\r\n", symbol->Name, fptr, line.LineNumber, symbol->Address ); + } + + printStack(); + + CloseDebugLog(); + MessageBox(NULL,"Program Error - program closing. See Debug Log for details","BPQ32",MB_ICONSTOP); + + exit(0); +} #endif @@ -1186,6 +1252,14 @@ int main(int argc, char * argv[]) } } + process = GetCurrentProcess(); + + SymSetOptions(SYMOPT_LOAD_LINES); + SymInitialize(process, NULL, TRUE ); + + AddVectoredExceptionHandler(1, UnhandledExcepFilter); + + #else state = backtrace_create_state(argv[0], 0, error_callback, NULL); diff --git a/MULTIPSK.c b/MULTIPSK.c index 8dc2d44..236b81f 100644 --- a/MULTIPSK.c +++ b/MULTIPSK.c @@ -507,7 +507,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) if (buffptr) { buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], - "MPSK} Error - Call missing from C command\r", STREAM->MyCall, STREAM->RemoteCall); + "MPSK} Error - Call missing from C command\r"); C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); } diff --git a/MailNode.vcproj b/MailNode.vcproj index ecc410d..b0d89e6 100644 --- a/MailNode.vcproj +++ b/MailNode.vcproj @@ -123,13 +123,15 @@ /> + + + + Debug + Win32 + + + Release + Win32 + + + + 18.0 + LinBPQ + {3766AA10-C777-4ED8-A83D-F1452DE9B666} + MailNode + Win32Proj + + + + Application + v145 + NotSet + true + + + Application + v145 + NotSet + + + + + + + + + + + + + <_ProjectFileVersion>18.0.12106.202 + + + C:\Dev\Msdev2005\$(SolutionName)\$(ProjectName)\$(Configuration)\ + C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(ProjectName)\$(Configuration)\ + true + + + C:\Dev\Msdev2005\$(SolutionName)\$(ProjectName)\$(Configuration)\ + C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(ProjectName)\$(Configuration)\ + false + + + + Disabled + Win32bits;..\BPQSource;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;LINBPQ;_USE_32BIT_TIME_T;NOMQTT;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + Level3 + EditAndContinue + + + kernel32.lib;WS2_32.Lib;Win32bits\libconfigd.lib;DbgHelp.lib;setupapi.lib;miniupnpc.lib;zlibstat.lib;%(AdditionalDependencies) + c:\LINBPQ\$(ProjectName).exe + true + true + c:\linbpq\linmail.map + Console + 4000000 + 0 + MachineX86 + + + + + Disabled + false + Win32bits;..\BPQSource;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_CONSOLE;LINBPQ;_USE_32BIT_TIME_T;NOMQTT;%(PreprocessorDefinitions) + MultiThreaded + + Level3 + EditAndContinue + + + kernel32.lib;WS2_32.Lib;Win32bits\libconfig.lib;DbgHelp.lib;Setupapi.lib;miniupnpc.lib;zlibstat.lib;%(AdditionalDependencies) + c:\devprogs\bpq32\LinBPQ.exe + true + Console + 5000000 + 10000000 + true + true + MachineX86 + + + + + + + + + + + + + + + + + + + All + $(IntDir) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Moncode.c b/Moncode.c index d437d96..b967615 100644 --- a/Moncode.c +++ b/Moncode.c @@ -34,6 +34,8 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #include "cheaders.h" #include "tncinfo.h" +extern char NCMPTypes[6][28]; + // MSGFLAG contains CMD/RESPONSE BITS #define CMDBIT 4 // CURRENT MESSAGE IS A COMMAND @@ -869,7 +871,7 @@ char * DISPLAY_NETROM(MESSAGE * ADJBUFFER, UCHAR * Output, int MsgLen) if (Index == 0x0F) // NCMP { - Output += sprintf((char *)Output, " NCMP %x %x Type %x Code %x", Index, ID, TXNO, RXNO); + Output += sprintf((char *)Output, " NCMP Type %s Code %x", NCMPTypes[TXNO & 15], RXNO); MsgLen = MsgLen - (19 + sizeof(void *)); diff --git a/RTKnown.txt b/RTKnown.txt new file mode 100644 index 0000000..e69de29 diff --git a/RigControl.c b/RigControl.c index 53ca2f3..c485792 100644 --- a/RigControl.c +++ b/RigControl.c @@ -2470,10 +2470,9 @@ DllExport BOOL APIENTRY Rig_Init() if (RIG->NumberofBands) CheckTimeBands(RIG); // Set initial timeband -#ifdef WIN32 if (RIG->PTTCATPort[0]) // Serial port RTS to CAT _beginthread(PTTCATThread,0,RIG); -#endif + if (RIG->HAMLIBPORT) { // Open listening socket @@ -3218,6 +3217,14 @@ int GetPermissionToChange(struct RIGPORTINFO * PORT, struct RIGINFO *RIG) // Get Permission to change + if (RIG->PTTTimer) // Dont allow change if PTT ia active + { + if (RIG->RIG_DEBUG) + Debugprintf("GetPermissionToChange - Blocked by active PTT"); + + return 0; + } + if (RIG->RIG_DEBUG) Debugprintf("GetPermissionToChange - WaitingForPermission = %d", RIG->WaitingForPermission); @@ -6075,6 +6082,8 @@ CheckOtherParams: ptr = strtok_s(NULL, " \t\n\r", &Context); +#ifdef WIN32 + while (memcmp(ptr, "COM", 3) == 0) { char * tncport = strlop(ptr, '/'); @@ -6092,6 +6101,14 @@ CheckOtherParams: if (ptr == NULL) break; } + +#else + + strcpy(RIG->PTTCATPort[0], _strlwr(ptr)); + ptr = strtok_s(NULL, " \t\n\r", &Context); + +#endif + if (ptr == NULL) break; else @@ -7710,6 +7727,56 @@ WaitAgain: } } */ +#else + +// Linux Version. Use with tty0tty Kernel Module. Only supports one device for now + +VOID PTTCATThread(void * Param) +{ + struct RIGINFO * RIG = (struct RIGINFO *)Param; + EndPTTCATThread = FALSE; + + Debugprintf("RigControl Opening %s for RTS PTT\n", RIG->PTTCATPort[0]); + + int fd = open(RIG->PTTCATPort[0], O_RDWR | O_NOCTTY); + if (fd < 0) + { + perror("Error opening serial port"); + return; + } + + while (1) + { + // 2. Block until the CTS line changes status + // The hardware interrupt wakes the driver, which wakes this ioctl + if (ioctl(fd, TIOCMIWAIT, TIOCM_CTS) < 0) + { + perror("ioctl TIOCMIWAIT failed"); + close(fd); + return; + } + + // 3. Determine if it went HIGH or LOW + int status; + ioctl(fd, TIOCMGET, &status); + + if (status & TIOCM_CTS) + { + Rig_PTTEx(RIG, TRUE, RIG->PTTCATTNC[0]); + } + else + { + Rig_PTTEx(RIG, FALSE, RIG->PTTCATTNC[0]); + } + } + + close(fd); + EndPTTCATThread = FALSE; + return; + +} + + #endif // HAMLIB Support Code diff --git a/TelnetV6.c b/TelnetV6.c index af88595..f261716 100644 --- a/TelnetV6.c +++ b/TelnetV6.c @@ -532,6 +532,9 @@ int ProcessLine(char * buf, int Port) else if (_stricmp(param,"SecureTelnet") == 0) TCP->SecureTelnet = atoi(value); + else if (_stricmp(param,"noWebSocks") == 0) + TCP->noWebSocks = atoi(value); + else if (_stricmp(param,"CloseOnDisconnect") == 0) TCP->DisconnectOnClose = atoi(value); @@ -547,6 +550,8 @@ int ProcessLine(char * buf, int Port) else if (_stricmp(param,"HTTPPORT") == 0) HTTPPort = TCP->HTTPPort = atoi(value); + + else if (_stricmp(param,"NETROMPORT") == 0) TCP->NETROMPort = atoi(value); diff --git a/UZ7HODrv.c b/UZ7HODrv.c index accf0d9..c5e0368 100644 --- a/UZ7HODrv.c +++ b/UZ7HODrv.c @@ -1166,7 +1166,7 @@ static size_t ExtProc(int fn, int port, PDATAMESSAGE buff) if (buffptr) { buffptr->Len = sprintf((UCHAR *)&buffptr->Data[0], - "UZ7HO} Error - Call missing from C command\r", STREAM->MyCall, STREAM->RemoteCall); + "UZ7HO} Error - Call missing from C command\r"); C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr); } diff --git a/Versions.h b/Versions.h index 8922ff2..d8cfb21 100644 --- a/Versions.h +++ b/Versions.h @@ -9,8 +9,8 @@ #endif -#define KVers 6,0,25,40 -#define KVerstring "6.0.25.40\0" +#define KVers 6,0,25,41 +#define KVerstring "6.0.25.41\0" #ifdef CKernel diff --git a/WebMail.c b/WebMail.c index 8f01ab1..4c3d3f8 100644 --- a/WebMail.c +++ b/WebMail.c @@ -1006,7 +1006,7 @@ int ViewWebMailMessage(struct HTTPConnectionInfo * Session, char * Reply, int Nu if (Msg == NULL) { ptr += sprintf(ptr, "Message %d not found\r\n", Number); - return sprintf(Reply, WebMailTemplate, BBSName, User->Call, Key, Key, Key, Key, Key, Key, Key, Message); + return sprintf(Reply, WebMailTemplate, BBSName, User->Call, Key, Key, Key, Key, Key, Key, Key, Key, Key, Key, Message); } // New Display so free any old values @@ -1019,7 +1019,7 @@ int ViewWebMailMessage(struct HTTPConnectionInfo * Session, char * Reply, int Nu if (!CheckUserMsg(Msg, User->Call, User->flags & F_SYSOP)) { ptr += sprintf(ptr, "Message %d not for you\r", Number); - return sprintf(Reply, WebMailTemplate, BBSName, User->Call, Key, Key, Key, Key, Key, Key, Key, Message); + return sprintf(Reply, WebMailTemplate, BBSName, User->Call, Key, Key, Key, Key, Key, Key, Key, Key, Key, Key, Message); } if (_stricmp(Msg->to, "RMS") == 0) diff --git a/Win32bits/bpq32.dll b/Win32bits/bpq32.dll deleted file mode 100644 index 616bbe1..0000000 Binary files a/Win32bits/bpq32.dll and /dev/null differ diff --git a/Win32bits/bpq32.exp b/Win32bits/bpq32.exp index d1fb2bd..3cb06aa 100644 Binary files a/Win32bits/bpq32.exp and b/Win32bits/bpq32.exp differ diff --git a/Win32bits/bpq32.lib b/Win32bits/bpq32.lib index 1fad5dd..f7fe014 100644 Binary files a/Win32bits/bpq32.lib and b/Win32bits/bpq32.lib differ diff --git a/WinmorControl.rc b/WinmorControl.rc index f43f2d3..4fd61a6 100644 --- a/WinmorControl.rc +++ b/WinmorControl.rc @@ -25,7 +25,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK #define BPQICON 400 -BPQICON ICON DISCARDABLE "..\BPQIcon.ICO" +BPQICON ICON DISCARDABLE "BPQIcon.ICO" // // Version diff --git a/WinmorControl.vcxproj b/WinmorControl.vcxproj new file mode 100644 index 0000000..d56cdef --- /dev/null +++ b/WinmorControl.vcxproj @@ -0,0 +1,150 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + 18.0 + {005A91EA-3A00-4FB4-ADD9-EB78DBFA2B82} + WinmorControl + 10.0 + + + + Application + v145 + false + + + Application + v145 + false + MultiByte + + + + + + + + + + + + + + + <_ProjectFileVersion>18.0.12106.202 + + + c:\DevProgs\bpq32\ + C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(ProjectName)\$(Configuration)\ + true + + + C:\Dev\Msdev2005\$(SolutionName)\$(ProjectName)\$(Configuration)\ + C:\Dev\Msdev2005\Intermed\$(SolutionName)\$(ProjectName)\$(Configuration)\ + false + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Debug/WinmorControl.tlb + + + + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + MultiThreadedDebug + .\Debug/WinmorControl.pch + $(IntDir) + $(IntDir) + $(IntDir) + Level3 + true + EditAndContinue + + + _DEBUG;%(PreprocessorDefinitions) + 0x0809 + + + WS2_32.Lib;Psapi.lib;Win32bits\bpq32.lib;%(AdditionalDependencies) + c:\DevProgs\bpq32\WinmorControl.exe + true + true + .\Debug/bpq32.pdb + true + c:\devprogs\bpq32\bpqpp.map + Windows + MachineX86 + + + true + .\Debug/WinmorControl.bsc + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release/WinmorControl.tlb + + + + MaxSpeed + OnlyExplicitInline + ..\cinclude;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + MultiThreaded + true + C:\msdev2005\Intermed\Release/WinmorControl.pch + $(IntDir) + $(IntDir) + $(IntDir) + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0809 + + + WS2_32.Lib;Psapi.lib;Win32bits\bpq32.lib;%(AdditionalDependencies) + c:\DevProgs\bpq32\WinmorControl.exe + true + .\Release/WinmorControl.pdb + true + c:\devprogs\bpq32\WinmorControl.map + Windows + MachineX86 + + + true + .\Release/WinmorControl.bsc + + + + + + + + + + + + \ No newline at end of file diff --git a/bpqether.c b/bpqether.c index 3ef2a00..cccb42a 100644 --- a/bpqether.c +++ b/bpqether.c @@ -56,7 +56,7 @@ along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses #include #include "pcap.h" -#include "../CommonSource/bpq32.h" +#include "bpq32.h" //#include "packet32.h" //#include "ntddndis.h" diff --git a/bpqtermTCP.c b/bpqtermTCP.c new file mode 100644 index 0000000..64ba1c8 --- /dev/null +++ b/bpqtermTCP.c @@ -0,0 +1,4170 @@ + +// Version 2.0.1 November 2007 + +// Change resizing algorith + + +// Version 2.0.2 January 2008 + +// Restore Checked state of Bells and AutoConnect Flags +// Call CheckTimer on startup (for new Initialisation Scheme for perl) + +// Version 2.0.3 July 2008 + +// Display lines received without a terminaing CR + + +// Version 2.0.4 November 2008 + +// Add option to remove a Line Feed following a CR +// Add Logging Option + +// Version 2.0.5 January 2009 + +// Add Start Minimized Option + +// Version 2.0.6 June 2009 + +// Add Option to send *** Disconnnected on disconnect +// Add line wrap code +// Add option not to monitor NODES broadcasts + +// Version 2.0.7 October 2009 + +// Add input buffer scrollback. +// Fix monitoring when PORTNUM specified + +// Version 2.0.8 December 2009 + +// Fix use of numeric keypad 2 and 8 (were treated as up and down) + +// Version 2.0.9 March 2010 + +// Add colour for monitor and BPQ Chat + +// Version 2.0.0 October 2010 + +// Add Chat Terminal Mode (sends keepalives) + +// Version 1.0.4.1 June 2012 + +// Add UIOnly Monitor Option + +// Version 1.0.5.1 November 2012 + +// Allow up to 8 hosts + +// Version 1.0.6.1 MY 2013 + +// Send Connect Failed prompt after setting terminal status + +// Version 1.0.7.1 Aug 2013 + +// Allow 16 hosts +// Save host setup when changed instead of on exit + + +// Version 1.0.8.1 ... + +// Operates in UTF-8 + +// Version 1.0.9.1 Aug 2014 + +// Add "alert on text" option + +// Version 1.0.10.1 Nov 2014 +// Fix possible crash on processing part line + +// Version 1.0.11.1 Feb 2015 +// Add "Alert after interval" feature +// Fix "Copy to Clipboard" + +// Version 1.0.12.1 Nov 2015 +// Add Port Names to Monitor Config and fix saving monitor option s by host + + +// Version 1.0.13.1 Sept 2016 + +// Fix buffer overrun introduced in 1.0.12.1 +// Fix saving Alert and Keyword filenames + +// Version 1.0.14.1 July 2017 + +// Add popup if keywords file can't be found + +// Version 1.0.15.1 Feb 2018 + +// Allow use of IPV6 even if host resolves to both V4 and V6 addresses (add IPV6: on front of hostname) +// Add Listen Mode +// Only send UTF-8 option if send in UTF-8 is set +// Drop received Keepalive packets + +// Version 1.0.16.1 ?? + +// Add YAPP File Transfer + +// Version 1.0.16.2 August 20203 + +// Support Monitoring 63 ports + +#define _CRT_SECURE_NO_DEPRECATE + +#include "winsock2.h" +#include "WS2tcpip.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +//#define _RICHEDIT_VER 0x0100 +#include +#define IDC_STATIC -1 +#include "bpqtermTCP.h" +#define TermTCP +#include "Versions.h" +#include "GetVersion.h" +#include "Shlobj.h" + +#define BPQICON 2 + +#define BGCOLOUR RGB(236,233,216) + +#define WSA_ACCEPT WM_USER + 1 +#define WSA_CONNECT WM_USER + 2 +#define WSA_DATA WM_USER + 3 + +#define BPQBASE 1100 + +HBRUSH bgBrush; + +HINSTANCE hInst; +TCHAR AppName[] = L"BPQTerm 32"; +TCHAR ClassName[] = L"BPQMAINWINDOW"; +TCHAR Title[80]; + +BOOL WINE; + +BOOL UseKeywords = TRUE; + +TCHAR KeyWordsName[MAX_PATH] = L"Keywords.sys"; +char ** KeyWords = NULL; +int NumberofKeyWords = 0; + +// YAPP stuff + +#define SOH 1 +#define STX 2 +#define ETX 3 +#define EOT 4 +#define ENQ 5 +#define ACK 6 +#define DLE 0x10 +#define NAK 0x15 +#define CAN 0x18 + + +UCHAR InputMode; // Normal or YAPP +WCHAR YAPPPath[MAX_PATH] = L""; // Path for saving YAPP Files + +// Foward declarations of functions included in this code module: + +ATOM MyRegisterClass(CONST WNDCLASS*); +BOOL InitApplication(HINSTANCE); +BOOL InitInstance(HINSTANCE, int); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); +int NewLine(); +VOID DoRefresh(struct RTFTerm * OPData); +VOID SendTraceOptions(); +int ProcessBuff(char * readbuff,int len); +VOID EnableConnectMenu(HWND hWnd); +VOID EnableDisconnectMenu(HWND hWnd); +VOID DisableConnectMenu(HWND hWnd); +VOID DisableDisconnectMenu(HWND hWnd); +VOID DisableYAPPMenu(HWND hWnd); +VOID EnableYAPPMenu(HWND hWnd); + +int DoReceivedData(HWND hWnd); +int DoStateChange(HWND hWnd); +int ToggleFlags(HWND hWnd, int Item, int mask); +int DoMonData(HWND hWnd); +int TogglePort(HWND hWnd, int Item, int mask); +int ToggleMTX(HWND hWnd); +int ToggleMCOM(HWND hWnd); +int ToggleMUI(HWND hWnd); +int ToggleParam(HWND hWnd, BOOL * Param, int Item); +int ToggleChat(HWND hWnd); +void MoveWindows(); +void CopyListToClipboard(HWND hWnd); +void CopyRichTextToClipboard(HWND hWnd); +BOOL OpenMonitorLogfile(); +void WriteMonitorLine(TCHAR * Msg, int MsgLen); +VOID WritetoOutputWindow(struct RTFTerm * OPData, TCHAR * Msg, int len); +int SendMsg(TCHAR * msg, int len); +TCPConnect(TCHAR * Host, int Port); +int Telnet_Connected(SOCKET sock, int Error); +VOID DataSocket_Read(SOCKET sock); +VOID Socket_Data(int sock, int error, int eventcode); +VOID Socket_Accept(int sock, int error, int eventcode); +SOCKET OpenListenSocket4(int port); +void YAPPSendFile(WCHAR * filename); +void QueueMsg(UCHAR * Msg, int Len); +BOOL ProcessYAPPMessage(UCHAR * Msg, int Len); + +COLORREF Colours[256] = {0, + RGB(0,0,0), RGB(0,0,128), RGB(0,0,192), RGB(0,0,255), // 1 - 4 + RGB(0,64,0), RGB(0,64,128), RGB(0,64,192), RGB(0,64,255), // 5 - 8 + RGB(0,128,0), RGB(0,128,128), RGB(0,128,192), RGB(0,128,255), // 9 - 12 + RGB(0,192,0), RGB(0,192,128), RGB(0,192,192), RGB(0,192,255), // 13 - 16 + RGB(0,255,0), RGB(0,255,128), RGB(0,255,192), RGB(0,255,255), // 17 - 20 + + RGB(64,0,0), RGB(64,0,128), RGB(64,0,192), RGB(0,0,255), // 21 + RGB(64,64,0), RGB(64,64,128), RGB(64,64,192), RGB(64,64,255), + RGB(64,128,0), RGB(64,128,128), RGB(64,128,192), RGB(64,128,255), + RGB(64,192,0), RGB(64,192,128), RGB(64,192,192), RGB(64,192,255), + RGB(64,255,0), RGB(64,255,128), RGB(64,255,192), RGB(64,255,255), + + RGB(128,0,0), RGB(128,0,128), RGB(128,0,192), RGB(128,0,255), // 41 + RGB(128,64,0), RGB(128,64,128), RGB(128,64,192), RGB(128,64,255), + RGB(128,128,0), RGB(128,128,128), RGB(128,128,192), RGB(128,128,255), + RGB(128,192,0), RGB(128,192,128), RGB(128,192,192), RGB(128,192,255), + RGB(128,255,0), RGB(128,255,128), RGB(128,255,192), RGB(128,255,255), + + RGB(192,0,0), RGB(192,0,128), RGB(192,0,192), RGB(192,0,255), // 61 + RGB(192,64,0), RGB(192,64,128), RGB(192,64,192), RGB(192,64,255), + RGB(192,128,0), RGB(192,128,128), RGB(192,128,192), RGB(192,128,255), + RGB(192,192,0), RGB(192,192,128), RGB(192,192,192), RGB(192,192,255), + RGB(192,255,0), RGB(192,255,128), RGB(192,255,192), RGB(192,2552,255), + + RGB(255,0,0), RGB(255,0,128), RGB(255,0,192), RGB(255,0,255), // 81 + RGB(255,64,0), RGB(255,64,128), RGB(255,64,192), RGB(255,64,255), + RGB(255,128,0), RGB(255,128,128), RGB(255,128,192), RGB(255,128,255), + RGB(255,192,0), RGB(255,192,128), RGB(255,192,192), RGB(255,192,255), + RGB(255,255,0), RGB(255,255,128), RGB(255,255,192), RGB(255,2552,255) +}; + +LRESULT APIENTRY InputProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ; +//LRESULT APIENTRY OutputProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ; +LRESULT APIENTRY MonProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ; +LRESULT APIENTRY SplitProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ; + + +LONG_PTR wpOrigInputProc; +//WNDPROC wpOrigOutputProc; +LONG_PTR wpOrigMonProc; +LONG_PTR wpOrigSplitProc; + +HWND hwndInput; +HWND hwndOutput; +HWND hwndMon; +HWND hwndSplit; + +HMENU trayMenu; + +#define AUTO -1 +#define CP437 437 +#define CP1251 1251 +#define CP1252 1252 + +int RXMode = AUTO; +int TXMode = CP_UTF8; + +int xsize,ysize; // Screen size at startup + +double Split=0.5; +int SplitPos=300; +#define SplitBarHeight 5 +#define InputBoxHeight 25 +RECT Rect; +RECT MonRect; +//RECT OutputRect; +RECT SplitRect; + +int OutputBoxHeight; + +int Height, Width, LastY; + +int maxlinelen = 80; + +#define MAXHOSTS 16 + +TCHAR Host[MAXHOSTS + 1][100] = {L"localhost"}; +int Port[MAXHOSTS + 1] = {0}; +TCHAR UserName[MAXHOSTS + 1][80] = {L""}; +TCHAR Password[MAXHOSTS + 1][80] = {L""}; +TCHAR MonParams[MAXHOSTS + 1][80] = {L""}; +int ListenPort = 8015; + +TCHAR HN[MAXHOSTS + 1][7] = {L"Host1", L"Host2", L"Host3", L"Host4", L"Host5", L"Host6", L"Host7", L"Host8", + L"Host9", L"Host10", L"Host11", L"Host12", L"Host13", L"Host14", L"Host15", L"Host16"}; +TCHAR PN[MAXHOSTS + 1][7] = {L"Port1", L"Port2", L"Port3", L"Port4", L"Port5", L"Port6", L"Port7", L"Port8", + L"Port9", L"Port10", L"Port11", L"Port12", L"Port13", L"Port14", L"Port15", L"Port16"}; +TCHAR UN[MAXHOSTS + 1][7] = {L"User1", L"User2", L"User3", L"User4", L"User5", L"User6", L"User7", L"User8", + L"User9", L"User10", L"User11", L"User12", L"User13", L"User14", L"User15", L"User16"}; +TCHAR MON[MAXHOSTS + 1][7] = {L"MON1", L"MON2", L"MON3", L"MON4", L"MON5", L"MON6", L"MON7", L"MON8", + L"MON9", L"MON10", L"MON11", L"MON12", L"MON13", L"MON14", L"MON15", L"MON16"}; +TCHAR PASSN[MAXHOSTS + 1][7] = {L"Pass1", L"Pass2", L"Pass3", L"Pass4", L"Pass5", L"Pass6", L"Pass7", L"Pass8", + L"Pass9", L"Pass10", L"Pass11", L"Pass12", L"Pass13", L"Pass14", L"Pass15", L"Pass16"}; + + +#define MAXLINES 1000 +#define LINELEN 200 + +char RTFHeader[4000]; + +int RTFHddrLen; + +typedef struct RTFTerm +{ + int CurrentLine; // Line we are writing to in circular buffer. + + int Index; + BOOL SendHeader; + BOOL Finished; + + TCHAR OutputScreen[MAXLINES][LINELEN]; + + int Colourvalue[MAXLINES]; + int LineLen[MAXLINES]; + int CharWidth; + int CurrentColour; + int Thumb; + int FirstTime; + int RTFHeight; // Height of RTF control in pixels + BOOL Scrolled; // Window is scrolled back + +}; + +TCHAR FontName[100] = L"Courier New"; +int FontSize = 20; +int FontWidth = 8; +int CodePage = 437; +int CharSet = 0; + + +struct RTFTerm OutputData; + +int CurrentHost = 0; +int CfgNo = 0; + +SOCKET sock = 0; +SOCKET ListenSock = 0; + +BOOL MonData = FALSE; + +TCHAR Key[80]; +uint64_t portmask=0; +int mtxparam=1; +int mcomparam=1; +int monUI=0; + +TCHAR kbbuf[250]; +int kbptr=0; +TCHAR readbuff[100000]; // for stupid bbs programs + +//int ptr=0; + +int Stream; +int len,count; + +TCHAR callsign[10]; +int state; +int change; + +int PartLinePtr=0; +int PartLineIndex=0; // Listbox index of (last) incomplete line + +BOOL Bells = FALSE; +BOOL StripLF = FALSE; +BOOL LogMonitor = FALSE; +BOOL LogOutput = FALSE; +BOOL SendDisconnected = TRUE; +BOOL MonitorNODES = TRUE; +BOOL MonitorColour = TRUE; +BOOL ChatMode = FALSE; +int MonPorts = 1; +BOOL ListenOn = FALSE; + +time_t LastWrite = 0xffffffff; +int AlertInterval = 300; +BOOL AlertBeep = TRUE; +int AlertFreq = 600; +int AlertDuration = 250; +TCHAR AlertFileName[MAX_PATH] = {0}; + +HANDLE MonHandle=INVALID_HANDLE_VALUE; + +HCURSOR DragCursor; +HCURSOR Cursor; + +BOOL MinimizetoTray=FALSE; +//BOOL StartMinimized = FALSE; + +HWND MainWnd, hWnd; + +BOOL SocketActive = FALSE; +BOOL Connecting = FALSE; +BOOL Connected = FALSE; +BOOL Disconnecting = FALSE; + +VOID CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime ); + +TIMERPROC lpTimerFunc = (TIMERPROC) TimerProc; + +int TimerHandle = 0; + +int SlowTimer; + +VOID __cdecl Debugprintf(const char * format, ...) +{ + char Mess[1000]; + va_list(arglist);int Len; + + va_start(arglist, format); + Len = vsprintf_s(Mess, sizeof(Mess), format, arglist); + strcat(Mess, "\r\n"); + OutputDebugStringA(Mess); + return; +} + + +VOID SaveIntValue(TCHAR * Key, int Value) +{ + TCHAR Val[100]; + + wsprintf(Val, L"%d", Value); + WritePrivateProfileString(L"Session 1", Key, Val, L".\\BPQTermTCP.ini"); +} + +VOID SaveStringValue(TCHAR * Key, TCHAR * Value) +{ + WritePrivateProfileString(L"Session 1", Key, Value, L".\\BPQTermTCP.ini"); +} + +int GetIntValue(TCHAR * Key, int Default) +{ + return GetPrivateProfileInt(L"Session 1", Key, Default, L".\\BPQTermTCP.ini"); +} + +VOID GetStringValue(TCHAR * Key, TCHAR * Value, int Len) +{ + GetPrivateProfileString(L"Session 1", Key, L"", Value, Len, L".\\BPQTermTCP.ini"); +} + +VOID CALLBACK TimerProc( + + HWND hwnd, // handle of window for timer messages + UINT uMsg, // WM_TIMER message + UINT idEvent, // timer identifier + DWORD dwTime) // current system time +{ + + // entered every 10 secs + + if (!Connected) + return; + + if (!ChatMode) + return; + + SlowTimer++; + + if (SlowTimer > 50) // About 9 mins + { + SlowTimer = 0; + SendMsg(L"\0", 1); + } +} + +VOID GetKeyWordFile() +{ + FILE * Handle; + DWORD FileSize; + char * ptr1, * ptr2; + struct stat STAT; + char * KeyWordFile; + + if (_wstat(KeyWordsName, &STAT) == -1) + { + if (UseKeywords) + { + TCHAR Dir[MAX_PATH]; + TCHAR Msg[512]; + GetCurrentDirectory(MAX_PATH, Dir); + wsprintf(Msg, L"Couldn't find file %s in %s", KeyWordsName, Dir); + MessageBox(NULL, Msg, L"BPQTermTCP", MB_OK); + } + return; + } + + FileSize = STAT.st_size; + + Handle = _wfopen(KeyWordsName, L"rb"); + + if (Handle == NULL) + return; + + KeyWordFile = malloc(FileSize+1); + + fread(KeyWordFile, 1, FileSize, Handle); + + fclose(Handle); + + KeyWordFile[FileSize]=0; + + _strlwr(KeyWordFile); // Compares are case-insensitive + + ptr1 = KeyWordFile; + + while (ptr1) + { + if (*ptr1 == '\n') ptr1++; + + ptr2 = strtok_s(NULL, "\r\n", &ptr1); + if (ptr2) + { + if (*ptr2 != '#') + { + KeyWords = realloc(KeyWords,(++NumberofKeyWords+1)*4); + KeyWords[NumberofKeyWords] = ptr2; + } + } + else + break; + } +} + +BOOL CheckKeyWord(char * Word, char * Msg) +{ + char * ptr1 = Msg, * ptr2; + int len = strlen(Word); + + while (*ptr1) // Stop at end + { + ptr2 = strstr(ptr1, Word); + + if (ptr2 == NULL) + return FALSE; // OK + + // Only bad if it ia not part of a longer word + + if ((ptr2 == Msg) || !(isalpha(*(ptr2 - 1)))) // No alpha before + if (!(isalpha(*(ptr2 + len)))) // No alpha after + return TRUE; // Bad word + + // Keep searching + + ptr1 = ptr2 + len; + } + + return FALSE; // OK +} + +BOOL CheckKeyWords(char * Msg, int len) +{ + char dupMsg[2048]; + int i; + + if (UseKeywords == 0 || NumberofKeyWords == 0) + return FALSE; + + memcpy(dupMsg, Msg, len); + dupMsg[len] = 0; + _strlwr(dupMsg); + + for (i = 1; i <= NumberofKeyWords; i++) + { + if (CheckKeyWord(KeyWords[i], dupMsg)) + { + Beep(660,250); + return TRUE; // Alert + } + } + + return FALSE; // OK + +} + + + +// +// FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int) +// +// PURPOSE: Entry point for the application. +// +// COMMENTS: +// +// This function initializes the application and processes the +// message loop. +// +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char * lpCmdLine, int nCmdShow) +{ + MSG msg; + TCHAR Size[80]; + + if (_stricmp(lpCmdLine, "Listen") == 0) + ListenOn = TRUE; + + if (!InitApplication(hInstance)) + return (FALSE); + + if (!InitInstance(hInstance, nCmdShow)) + return (FALSE); + + if (ListenOn == TRUE) + { + DisableConnectMenu(hWnd); + ListenSock = OpenListenSocket4(ListenPort); + } + + DisableYAPPMenu(hWnd); + + // Main message loop: + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + SaveIntValue(L"PortMask", portmask); + SaveIntValue(L"Bells", Bells); + SaveIntValue(L"StripLF", StripLF); + + SaveIntValue(L"MTX",mtxparam); + SaveIntValue(L"MCOM", mcomparam); + SaveIntValue(L"MUIONLY", monUI); + +#pragma warning(push) +#pragma warning(disable:4244) + SaveIntValue(L"Split", Split * 100); +#pragma warning(pop) + + SaveIntValue(L"MONColour", MonitorColour); + SaveIntValue(L"MonNODES", MonitorNODES); + SaveIntValue(L"MonPorts", MonPorts); + SaveIntValue(L"ChatMode", ChatMode); + SaveIntValue(L"CurrentHost", CurrentHost); + + wsprintf(Size,L"%d,%d,%d,%d",Rect.left,Rect.right,Rect.top,Rect.bottom); + SaveStringValue(L"Size", Size); + + SaveStringValue(L"FontName", FontName); + SaveIntValue(L"CharSet", CharSet); + SaveIntValue(L"CodePage", CodePage); + SaveIntValue(L"FontSize", FontSize); + SaveIntValue(L"FontWidth", FontWidth); + SaveIntValue(L"AlertInterval", AlertInterval); + + KillTimer(NULL, TimerHandle); + + return (msg.wParam); +} + +// + +// +// FUNCTION: InitApplication(HANDLE) +// +// PURPOSE: Initializes window data and registers window class +// +// COMMENTS: +// +// In this function, we initialize a window class by filling out a data +// structure of type WNDCLASS and calling either RegisterClass or +// the internal MyRegisterClass. +// +BOOL InitApplication(HINSTANCE hInstance) +{ + WNDCLASS wc; + + bgBrush = CreateSolidBrush(BGCOLOUR); + + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WndProc; + + wc.cbClsExtra = 0; + wc.cbWndExtra = DLGWINDOWEXTRA; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(BPQICON)); + wc.hCursor = NULL; //LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = bgBrush; + + wc.lpszMenuName = NULL; + wc.lpszClassName = ClassName; + + return (RegisterClass(&wc)); + +} + +HMENU hMenu, hPopMenu1, hPopMenu2, hPopMenu3; // handle of menu + +VOID SetupRTFHddr() +{ + int i, n; + char RTFColours[3000]; + char Temp[1000]; + + // Set up RTF Header, including Colours String; + + memcpy(RTFColours, "{\\colortbl ;", 12); + n = 12; + + for (i = 1; i < 100; i++) + { + COLORREF Colour = Colours[i]; + n += sprintf(&RTFColours[n], "\\red%d\\green%d\\blue%d;", GetRValue(Colour), GetGValue(Colour),GetBValue(Colour)); + } + + RTFColours[n++] = '}'; + RTFColours[n] = 0; + +// wcscpy(RTFHeader, "{\\rtf1\\deff0{\\fonttbl{\\f0\\fmodern\\fprq1\\fcharset204 ;}}"); + sprintf(RTFHeader, "{\\rtf1\\deff0{\\fonttbl{\\f0\\fprq1\\cpg%d\\fcharset%d %s;}}", CodePage, CharSet, FontName); + sprintf(RTFHeader, "{\\rtf1\\deff0{\\fonttbl{\\f0\\fmodern\\fprq1;}}"); + strcat(RTFHeader, RTFColours); + sprintf(Temp, "\\viewkind4\\uc1\\pard\\f0\\fs%d\\uc0", FontSize); + strcat(RTFHeader, Temp); + + RTFHddrLen = strlen(RTFHeader); +} + +TCHAR VersionStringW[100]; + +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + int i, n, tempmask=0xffff; + TCHAR msg[20]; + TCHAR Size[80]; + WSADATA WsaData; // receives data from WSAStartup + struct RTFTerm * OPData; + int retCode; + HKEY hKey=0; + + hInst = hInstance; // Store instance handle in our global variable + + WSAStartup(MAKEWORD(2, 0), &WsaData); + + // See if running under WINE + + retCode = RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"SOFTWARE\\Wine", 0, KEY_QUERY_VALUE, &hKey); + + if (retCode == ERROR_SUCCESS) + { + RegCloseKey(hKey); + WINE =TRUE; + Debugprintf("Running under WINE"); + } +// Get saved config from ini + +// MonitorNODES = GetIntValue("MonNODES", 0); + MonPorts = GetIntValue(L"MonPorts", 0); +// mtxparam = GetIntValue("MTX", 0); +// mcomparam = GetIntValue("MCOM", 0); +// monUI = GetIntValue("MUIONLY", 0); + tempmask = GetIntValue(L"PortMask", 0); + ChatMode = GetIntValue(L"ChatMode", 0); + MonitorColour = GetIntValue(L"MONColour", 0); + Bells = GetIntValue(L"Bells", 0); + StripLF = GetIntValue(L"StripLF", 0); + CurrentHost = GetIntValue(L"CurrentHost", 0); + Split = GetIntValue(L"Split", 0); + if (Split == 0) + Split = 50; + + Split /= 100; // Stored as a %,used as 0 - 1 + + for (n = 0; n < MAXHOSTS; n++) + { + GetStringValue(HN[n], Host[n], 100); + GetStringValue(UN[n], UserName[n], 80); + GetStringValue(PASSN[n], Password[n], 80); + Port[n] = GetIntValue(PN[n], 0); + GetStringValue(MON[n], MonParams[n], 80); + } + + n = swscanf(MonParams[CurrentHost], L"%x %x %x %x %x %x", + &portmask, &mtxparam, &mcomparam, &MonitorNODES, &MonitorColour, &monUI); + + +// GetStringValue(L"FontName", FontName, 99); + +// if (FontName[0] == 0) +// wcscpy(FontName, L"Courier New"); + +// CharSet = GetIntValue(L"CharSet", 0); +// CodePage = GetIntValue(L"CodePage", 437); + + FontSize = GetIntValue(L"FontSize", 20); + FontWidth = GetIntValue(L"FontWidth", 8); + RXMode = GetIntValue(L"RXMODE", -1); + TXMode = GetIntValue(L"TXMODE", CP_UTF8); + + AlertInterval = GetIntValue(L"AlertInterval", 3600); + AlertBeep = GetIntValue(L"AlertBeep", 1); + AlertFreq = GetIntValue(L"AlertFreq", 600); + AlertDuration = GetIntValue(L"AlertDuration", 250); + + GetStringValue(L"AlertFileName", AlertFileName, MAX_PATH - 1); + + ListenPort = GetIntValue(L"ListenPort", 8515); + + UseKeywords = GetIntValue(L"UseKeywords", 1); + GetStringValue(L"AlertKeyFile", KeyWordsName, MAX_PATH - 1); + + if (UseKeywords && KeyWordsName[0] == 0) + wcscpy(&KeyWordsName[0], L"Keywords.sys"); + + GetStringValue(L"YAPPPath", YAPPPath, MAX_PATH - 1); + + + OutputData.CharWidth = FontWidth; + + // Create a dialog box as the main window + + hWnd = CreateDialog(hInst,ClassName,0,NULL); + + if (!hWnd) + return (FALSE); + + MainWnd=hWnd; + + GetStringValue(L"Size", Size, 80); + swscanf(Size,L"%d,%d,%d,%d",&Rect.left,&Rect.right,&Rect.top,&Rect.bottom); + + if (Rect.right < 100 || Rect.bottom < 100) + { + GetWindowRect(hWnd, &Rect); + } + + Height = Rect.bottom-Rect.top; + Width = Rect.right-Rect.left; + +#pragma warning(push) +#pragma warning(disable:4244) + SplitPos=Height*Split; +#pragma warning(pop) + + SetupRTFHddr(); + + // Create a Rich Text Control + + OPData = &OutputData; + + OPData->SendHeader = TRUE; + OPData->Finished = TRUE; + OPData->CurrentColour = 1; + + LoadLibrary(L"riched20.dll"); + + hwndOutput = CreateWindowEx(WS_EX_CLIENTEDGE, RICHEDIT_CLASS, L"", + WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_NOHIDESEL | WS_VSCROLL | ES_READONLY, + 6,145,290,130, MainWnd, NULL, hInstance, NULL); + + // Register for Mouse Events for Copy/Paste + + SendMessage(hwndOutput, EM_SETEVENTMASK, (WPARAM)0, (LPARAM)ENM_MOUSEEVENTS | ENM_SCROLLEVENTS | ENM_KEYEVENTS); + SendMessage(hwndOutput, EM_EXLIMITTEXT, 0, MAXLINES * LINELEN); + + trayMenu = CreatePopupMenu(); + + AppendMenu(trayMenu,MF_STRING,40000,L"Copy"); + + // Retrieve the handlse to the edit controls. + + hwndInput = GetDlgItem(hWnd, 118); + hwndSplit = GetDlgItem(hWnd, 119); + hwndMon = GetDlgItem(hWnd, 116); + + // Set our own WndProcs for the controls. + + wpOrigInputProc = (WNDPROC) SetWindowLongPtr(hwndInput, GWLP_WNDPROC, InputProc); + wpOrigMonProc = (WNDPROC)SetWindowLongPtr(hwndMon, GWLP_WNDPROC, MonProc); + wpOrigSplitProc = (WNDPROC)SetWindowLongPtr(hwndSplit, GWLP_WNDPROC, SplitProc); + + MoveWindow(hWnd,Rect.left,Rect.top, Rect.right-Rect.left, Rect.bottom-Rect.top, TRUE); + + MoveWindows(); + + GetVersionInfo(NULL); + + mbstowcs(VersionStringW, VersionString, 50); + + if (ListenOn) + wsprintf(Title,L"BPQTermTCP Version %s Listening for Calls", VersionStringW); + else + wsprintf(Title,L"BPQTermTCP Version %s", VersionStringW); + + SetWindowText(hWnd,Title); + + hMenu=GetMenu(hWnd); + + hPopMenu1=GetSubMenu(hMenu,4); + + if (ListenOn == 0) + { + for (i = 1; i <= MonPorts; i++) + { + wsprintf(msg,L"Port %d",i); + + if (tempmask & (1<<(i-1))) + { + AppendMenu(hPopMenu1,MF_STRING | MF_CHECKED,BPQBASE + i, &msg[0]); + portmask |= ((uint64_t)1<<(i-1)); + } + else + AppendMenu(hPopMenu1,MF_STRING | MF_UNCHECKED,BPQBASE + i, &msg[0]); + } + } + CheckMenuItem(hMenu, BPQMTX, (mtxparam) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, BPQMCOM, (mcomparam) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MUIONLY, (monUI) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, BPQBELLS, (Bells) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, BPQStripLF, (StripLF) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, BPQMNODES, (MonitorNODES) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MONCOLOUR, (MonitorColour) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, CHATTERM, (ChatMode) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, BPQBELLS, (Bells) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, BPQENABLE, (ListenOn) ? MF_CHECKED : MF_UNCHECKED); + + for (i = 0; i < MAXHOSTS; i++) + { + if (Host[i][0]) + { + ModifyMenu(hMenu, IDC_HOST1 + i, MF_BYCOMMAND, IDC_HOST1 + i, Host[i]); + ModifyMenu(hMenu, BPQCONNECT1 + i, MF_BYCOMMAND, BPQCONNECT1 + i, Host[i]); + } + } + + EnableMenuItem(hMenu,BPQDISCONNECT,MF_GRAYED); + + DrawMenuBar(hWnd); + + DragCursor = LoadCursor(hInstance, L"IDC_DragSize"); + Cursor = LoadCursor(NULL, IDC_ARROW); + + if ((nCmdShow == SW_SHOWMINIMIZED) || (nCmdShow == SW_SHOWMINNOACTIVE)) + if (MinimizetoTray) + ShowWindow(hWnd, SW_HIDE); + else + ShowWindow(hWnd, nCmdShow); + else + ShowWindow(hWnd, nCmdShow); + + UpdateWindow(hWnd); + + GetKeyWordFile(); // Words/Phrases to alert on + + TimerHandle = SetTimer(NULL, 0, 10000, lpTimerFunc); + + return (TRUE); +} + + +INT_PTR CALLBACK ConfigWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + int n; + + switch (message) + { + case WM_INITDIALOG: + + SetDlgItemText(hDlg, IDC_HOST, Host[CfgNo]); + SetDlgItemInt(hDlg, IDC_PORT, Port[CfgNo], FALSE); + SetDlgItemText(hDlg, IDC_USER, UserName[CfgNo]); + SetDlgItemText(hDlg, IDC_PASS, Password[CfgNo]); + + 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: + + switch (LOWORD(wParam)) + { + case IDOK: + + GetDlgItemText(hDlg, IDC_HOST, Host[CfgNo], 99); + Port[CfgNo] = GetDlgItemInt(hDlg, IDC_PORT,NULL, FALSE); + GetDlgItemText(hDlg, IDC_USER, UserName[CfgNo], 79); + GetDlgItemText(hDlg, IDC_PASS, Password[CfgNo], 79); + + ModifyMenu(hMenu, BPQCONNECT1 + CfgNo, MF_BYCOMMAND, BPQCONNECT1 + CfgNo, Host[CfgNo]); + ModifyMenu(hMenu, IDC_HOST1 + CfgNo, MF_BYCOMMAND, IDC_HOST1 + CfgNo, Host[CfgNo]); + + for (n = 0; n < MAXHOSTS; n++) + { + SaveStringValue(HN[n], Host[n]); + SaveStringValue(UN[n], UserName[n]); + SaveStringValue(PASSN[n], Password[n]); + SaveIntValue(PN[n], Port[n]); + SaveStringValue(MON[n], MonParams[n]); + } + + + case IDCANCEL: + + EndDialog(hDlg, LOWORD(wParam)); + return TRUE; + } + } + + return FALSE; + +} + +INT_PTR CALLBACK ListenWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + + SetDlgItemInt(hDlg, IDC_LISTENPORT, ListenPort, FALSE); + + 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: + + switch (LOWORD(wParam)) + { + case IDOK: + + ListenPort = GetDlgItemInt(hDlg, IDC_LISTENPORT,NULL, FALSE); + + SaveIntValue(L"ListenPort", ListenPort); + + case IDCANCEL: + + EndDialog(hDlg, LOWORD(wParam)); + return TRUE; + } + } + + return FALSE; + +} + +INT_PTR CALLBACK AlertConfigWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + + SetDlgItemInt(hDlg, IDC_ALERTINTERVAL, AlertInterval, FALSE); + if (AlertBeep) + CheckDlgButton(hDlg, IDC_RADIO1, TRUE); + else + CheckDlgButton(hDlg, IDC_RADIO2, TRUE); + + SetDlgItemInt(hDlg, IDC_FREQ, AlertFreq, FALSE); + SetDlgItemInt(hDlg, IDC_DURATION, AlertDuration, FALSE); + SetDlgItemText(hDlg, IDC_ALERTFILENAME, &AlertFileName[0]); + + CheckDlgButton(hDlg, IDC_USEKEYWORDS, UseKeywords); + SetDlgItemText(hDlg, IDC_ALERTKEYNAME, &KeyWordsName[0]); + + 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: + switch (LOWORD(wParam)) + { + case IDOK: + + AlertInterval = GetDlgItemInt(hDlg, IDC_ALERTINTERVAL, NULL, FALSE); + AlertBeep = IsDlgButtonChecked(hDlg,IDC_RADIO1); + AlertFreq = GetDlgItemInt(hDlg, IDC_FREQ, NULL, FALSE); + AlertDuration = GetDlgItemInt(hDlg, IDC_DURATION, NULL, FALSE); + UseKeywords = IsDlgButtonChecked(hDlg, IDC_USEKEYWORDS); + + GetDlgItemText(hDlg, IDC_ALERTFILENAME, &AlertFileName[0], MAX_PATH-1 ); + GetDlgItemText(hDlg, IDC_ALERTKEYNAME, &KeyWordsName[0], MAX_PATH-1 ); + + SaveIntValue(L"AlertInterval", AlertInterval); + SaveIntValue(L"AlertBeep", AlertBeep); + SaveIntValue(L"AlertFreq", AlertFreq); + SaveIntValue(L"AlertDuration", AlertDuration); + + SaveIntValue(L"UseKeywords", UseKeywords); + SaveStringValue(L"AlertKeyFile", KeyWordsName); + + SaveStringValue(L"AlertFileName", AlertFileName); + EndDialog(hDlg, LOWORD(wParam)); + return TRUE; + + case IDCANCEL: + + EndDialog(hDlg, LOWORD(wParam)); + return TRUE; + } + } + + return FALSE; + +} + + + +INT_PTR CALLBACK FontConfigWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + POINT Point; + int Min, Max; + + switch (message) + { + case WM_INITDIALOG: + + if (RXMode == AUTO) + CheckDlgButton(hDlg, IDC_AUTO, BST_CHECKED); + else if (RXMode == CP1251) + CheckDlgButton(hDlg, IDC_1251, BST_CHECKED); + else if (RXMode == CP1252) + CheckDlgButton(hDlg, IDC_1252, BST_CHECKED); + else if (RXMode == CP437) + CheckDlgButton(hDlg, IDC_437, BST_CHECKED); + + if (TXMode == CP_UTF8) + CheckDlgButton(hDlg, IDC_UTF8, BST_CHECKED); + else if (TXMode == CP1251) + CheckDlgButton(hDlg, IDC_Send1251, BST_CHECKED); + else if (TXMode == CP1252) + CheckDlgButton(hDlg, IDC_Send1252, BST_CHECKED); + + SetDlgItemInt(hDlg, IDC_FONTSIZE, FontSize, FALSE); + SetDlgItemInt(hDlg, IDC_FONTWIDTH, FontWidth, FALSE); + + 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: + switch (LOWORD(wParam)) + { + case IDOK: + +// GetDlgItemText(hDlg, IDC_FONTNAME, FontName, 99); +// CharSet = GetDlgItemInt(hDlg, IDC_CHARSET, NULL, FALSE); +// CodePage = GetDlgItemInt(hDlg, IDC_CODEPAGE, NULL, FALSE); + + FontSize = GetDlgItemInt(hDlg, IDC_FONTSIZE, NULL, FALSE); + FontWidth = GetDlgItemInt(hDlg, IDC_FONTWIDTH, NULL, FALSE); + + if (IsDlgButtonChecked(hDlg, IDC_AUTO)) + RXMode = AUTO; + else if (IsDlgButtonChecked(hDlg, IDC_1251)) + RXMode = CP1251; + else if (IsDlgButtonChecked(hDlg, IDC_1252)) + RXMode = CP1252; + else if (IsDlgButtonChecked(hDlg, IDC_437)) + RXMode = CP437; + + if (IsDlgButtonChecked(hDlg, IDC_UTF8)) + TXMode = CP_UTF8; + else if (IsDlgButtonChecked(hDlg, IDC_Send1251)) + TXMode = CP1251; + else if (IsDlgButtonChecked(hDlg, IDC_Send1252)) + TXMode = CP1252; + +// SaveStringValue(L"FontName", FontName); +// SaveIntValue(L"CharSet", CharSet); +// SaveIntValue(L"CodePage", CodePage); + SaveIntValue(L"FontSize", FontSize); + SaveIntValue(L"FontWidth", FontWidth); + SaveIntValue(L"RXMODE", RXMode); + SaveIntValue(L"TXMODE", TXMode); + + OutputData.CharWidth = FontWidth; + + SetupRTFHddr(); + + Point.x = 0; + Point.y = 25000; // Should be plenty for any font + + SendMessage(hwndOutput, EM_SETSCROLLPOS, 0, (LPARAM) &Point); + OutputData.Scrolled = FALSE; + + GetScrollRange(hwndOutput, SB_VERT, &Min, &Max); // Get Actual Height + OutputData.RTFHeight = Max; + + DoRefresh(&OutputData); + + return TRUE; + + case IDCANCEL: + + EndDialog(hDlg, LOWORD(wParam)); + return TRUE; + } + } + + return FALSE; + +} + + +// +// FUNCTION: WndProc(HWND, unsigned, WORD, LONG) +// +// PURPOSE: Processes messages for the main window. +// + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int wmId, wmEvent; + LPRECT lprc; + TCHAR Buffer[1000]; + TCHAR * buf = Buffer; + TEXTMETRIC tm; + int y, i; + LPMEASUREITEMSTRUCT lpmis; + LPDRAWITEMSTRUCT lpdis; + OPENFILENAME ofn; + WCHAR FN[MAX_PATH] = L""; + BROWSEINFO bi; + LPITEMIDLIST pidl; + char Mess[64]; + + + switch (message) + { + case WSA_DATA: // Notification on data socket + + Socket_Data(wParam, WSAGETSELECTERROR(lParam), WSAGETSELECTEVENT(lParam)); + return 0; + + case WSA_ACCEPT: /* Notification if a socket connection is pending. */ + + Socket_Accept(wParam, WSAGETSELECTERROR(lParam), WSAGETSELECTEVENT(lParam)); + return 0; + + case WSA_CONNECT: /* Notification if a socket connection is pending. */ + + Telnet_Connected(wParam, WSAGETSELECTERROR(lParam)); + return 0; + +// case WM_CREATE: + +// SendMessage(hWndRichEdit, EM_SETEVENTMASK, (WPARAM)0 (LPARAM)ENM_MOUSEEVENTS); +// break; + + + case WM_CTLCOLOREDIT: + + if (OutputData.Scrolled) + { + HDC hdcStatic = (HDC)wParam; + SetBkMode(hdcStatic, TRANSPARENT); + + return (LONG)GetStockObject(LTGRAY_BRUSH); + } + return (DefWindowProc(hWnd, message, wParam, lParam)); + + case WM_NOTIFY: + { + const MSGFILTER * pF = (MSGFILTER *)lParam; + POINT pos; + CHARRANGE Range; + + if(pF->nmhdr.hwndFrom == hwndOutput) + { + if(pF->msg == WM_VSCROLL) + { +// OutputData.Thumb = SendMessage(hwndOutput, EM_GETTHUMB, 0, 0); + DoRefresh(&OutputData); +// return TRUE; + } + + if(pF->msg == WM_KEYUP) + { + if (pF->wParam == VK_PRIOR || pF->wParam == VK_NEXT) + { +// OutputData.Thumb = SendMessage(hwndOutput, EM_GETTHUMB, 0, 0); + DoRefresh(&OutputData); + } + } + + if(pF->msg == WM_RBUTTONDOWN) + { + // Only allow popup if something is selected + + SendMessage(hwndOutput, EM_EXGETSEL , 0, (WPARAM)&Range); + if (Range.cpMin == Range.cpMax) + return TRUE; + + GetCursorPos(&pos); + TrackPopupMenu(trayMenu, 0, pos.x, pos.y, 0, hWnd, 0); + return TRUE; + } + } + break; + } + + case WM_MEASUREITEM: + + lpmis = (LPMEASUREITEMSTRUCT) lParam; + return TRUE; + + case WM_DRAWITEM: + + lpdis = (LPDRAWITEMSTRUCT) lParam; + + // If there are no list box items, skip this message. + + if (lpdis->itemID == -1) + { + return TRUE; + } + + switch (lpdis->itemAction) + { + case ODA_SELECT: + case ODA_DRAWENTIRE: + + // if Chat Console, and message has a colour eacape, action it + + SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID, (LPARAM) Buffer); + + GetTextMetrics(lpdis->hDC, &tm); + + y = (lpdis->rcItem.bottom + lpdis->rcItem.top - tm.tmHeight) / 2; + + if (Buffer[0] == 0x1b) + { + SetTextColor(lpdis->hDC, Colours[Buffer[1] - 10]); + buf += 2; + } +// SetBkColor(lpdis->hDC, 0); + + TextOut(lpdis->hDC, + 6, + y, + buf, + wcslen(buf)); + + // SetTextColor(lpdis->hDC, OldColour); + + break; + } + + return TRUE; + + case WM_ACTIVATE: + + SetFocus(hwndInput); + break; + + + + case WM_COMMAND: + + wmId = LOWORD(wParam); // Remember, these are... + wmEvent = HIWORD(wParam); // ...different for Win32! + + //Parse the menu selections: + + if (wmId > BPQBASE && wmId <= BPQBASE + 64) + { + TogglePort(hWnd,wmId,0x1 << (wmId - (BPQBASE + 1))); + break; + } + + if (wmId >= BPQCONNECT1 && wmId < BPQCONNECT1 + MAXHOSTS) + { + CurrentHost = wmId - BPQCONNECT1; + + i = swscanf(MonParams[CurrentHost], L"%llx %x %x %x %x %x", + &portmask, &mtxparam, &mcomparam, &MonitorNODES, &MonitorColour, &monUI); + + for (i = 1; i <= MonPorts; i++) + { + if (portmask & ((uint64_t)1<<(i-1))) + CheckMenuItem(hMenu, BPQBASE + i, MF_CHECKED); + else + CheckMenuItem(hMenu, BPQBASE + i, MF_UNCHECKED); + + } + + CheckMenuItem(hMenu, BPQMCOM, (mcomparam) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, MUIONLY, (monUI) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, BPQMTX, (mtxparam) ? MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hMenu, BPQMNODES, (MonitorNODES) ? MF_CHECKED : MF_UNCHECKED); + + + TCPConnect(Host[CurrentHost], Port[CurrentHost]); + break; + } + + if (wmId >= IDC_HOST1 && wmId < IDC_HOST1 + MAXHOSTS) + { + CfgNo = wmId - IDC_HOST1; + + DialogBox(hInst, MAKEINTRESOURCE(IDD_CONFIG), hWnd, ConfigWndProc); + break; + } + + switch (wmId) + { + case BPQPORT: + + DialogBox(hInst, MAKEINTRESOURCE(IDD_LISTEN), hWnd, ListenWndProc); + break; + + + case 40000: + { + int len=0; + HGLOBAL hMem; + char * ptr; + CHARRANGE Range; + + // Copy Rich Text Selection to Clipboard + + SendMessage(hwndOutput, EM_EXGETSEL , 0, (WPARAM)&Range); + + hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (Range.cpMax - Range.cpMin + 1) * 2); + + if (hMem != 0) + { + ptr=GlobalLock(hMem); + + if (OpenClipboard(MainWnd)) + { + len = SendMessage(hwndOutput, EM_GETSELTEXT , 0, (WPARAM)ptr); + + GlobalUnlock(hMem); + EmptyClipboard(); + SetClipboardData(CF_UNICODETEXT,hMem); + CloseClipboard(); + } + } + else + GlobalFree(hMem); + + SetFocus(hwndInput); + return TRUE; + } + + case BPQMTX: + + ToggleMTX(hWnd); + break; + + case BPQMCOM: + + ToggleMCOM(hWnd); + break; + + case MUIONLY: + + ToggleMUI(hWnd); + break; + + case BPQDISCONNECT: + + if (Disconnecting) + { + // Force close + + if (SocketActive) + closesocket(sock); + + wsprintf(Title, L"BPQTermTCP Version %s - Disconnected", VersionStringW); + SetWindowText(hWnd,Title); + DisableDisconnectMenu(hWnd); + DisableYAPPMenu(hWnd); + EnableConnectMenu(hWnd); + + WritetoOutputWindow(&OutputData , L"*** Disconnected\r", 17); + DoRefresh(&OutputData); + SocketActive = FALSE; + Connected = FALSE; + Disconnecting = FALSE; + InputMode = 0; + + break; + } + + shutdown(sock, 2); // SD_BOTH + Disconnecting = TRUE; + break; + + case BPQBELLS: + + ToggleParam(hWnd, &Bells, BPQBELLS); + break; + + case BPQENABLE: + + ToggleParam(hWnd, &ListenOn, BPQENABLE); + if (ListenOn) + { + DisableConnectMenu(hWnd); + ListenSock = OpenListenSocket4(ListenPort); + } + else + { + EnableConnectMenu(hWnd); + closesocket(ListenSock); + } + + break; + + + case BPQStripLF: + + ToggleParam(hWnd, &StripLF, BPQStripLF); + break; + + case BPQLogOutput: + + ToggleParam(hWnd, &LogOutput, BPQLogOutput); + break; + + case CHATTERM: + + ToggleParam(hWnd, &ChatMode, CHATTERM); + break; + + + case ID_SETUP_FONT: + + DialogBox(hInst, MAKEINTRESOURCE(IDD_FONT), hWnd, FontConfigWndProc); + break; + + case ID_SETUP_ALERTSETUP: + + DialogBox(hInst, MAKEINTRESOURCE(IDD_ALERTDLG), hWnd, AlertConfigWndProc); + break; + + case BPQMNODES: + + ToggleParam(hWnd, &MonitorNODES, BPQMNODES); + SendTraceOptions(); + break; + + + case MONITOR_ADDPORT: + + wsprintf(Buffer, L"Port %d", ++MonPorts); + + AppendMenu(hPopMenu1,MF_STRING | MF_UNCHECKED,BPQBASE + MonPorts, Buffer); + + + case MONCOLOUR: + + ToggleParam(hWnd, &MonitorColour, MONCOLOUR); + SendTraceOptions(); + break; + + case BPQLogMonitor: + + ToggleParam(hWnd, &LogMonitor, BPQLogMonitor); + break; + + case BPQCLEARMON: + + SendMessage(hwndMon,LB_RESETCONTENT, 0, 0); + break; + + case BPQCLEAROUT: + + for (i = 0; i < MAXLINES; i++) + { + OutputData.OutputScreen[i][0] = 0; + } + + OutputData.CurrentLine = 0; + DoRefresh(&OutputData); + break; + + case BPQCOPYMON: + + CopyListToClipboard(hwndMon); + break; + + case BPQCOPYOUT: + + CopyRichTextToClipboard(hwndOutput); + break; + + case BPQHELP: + +// HtmlHelp(hWnd,"BPQTerminal.chm",HH_HELP_FINDER,0); + break; + + case YAPPSEND: + + memset(&ofn, 0, sizeof (OPENFILENAME)); + ofn.lStructSize = sizeof (OPENFILENAME); + ofn.hwndOwner = hWnd; + ofn.lpstrFile = FN; + ofn.nMaxFile = 250; + ofn.lpstrTitle = L"File to send"; +// ofn.lpstrInitialDir = BPQDirectory; + + // Turn off monitoring + + len = sprintf(Mess, "\\\\\\\\%x %x %x %x %x %x %x %x\r", 0, 0, 0, 0, 0, 0, 0, 0); + send(sock, Mess, len, 0); + + + if (GetOpenFileName(&ofn)) + YAPPSendFile(FN); + else + SendTraceOptions(); + break; + + + case YAPPDIR: + + memset(&bi, 0, sizeof (BROWSEINFO)); + + bi.hwndOwner = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = FN; + bi.lpszTitle = L"Please select a folder for storing received files"; + bi.ulFlags = BIF_RETURNONLYFSDIRS; + bi.lParam = 0; + bi.iImage = 0; + + pidl = SHBrowseForFolder(&bi); + + if (pidl) + { + SHGetPathFromIDList(pidl, YAPPPath); + wcscat(YAPPPath, L"\\"); + SaveStringValue(L"YAPPPath", YAPPPath); + } + + break; + + + + default: + + return 0; + + } + + case WM_SYSCOMMAND: + + wmId = LOWORD(wParam); // Remember, these are... + wmEvent = HIWORD(wParam); // ...different for Win32! + + switch (wmId) { + + case SC_RESTORE: + + case SC_MINIMIZE: + + default: + + return (DefWindowProc(hWnd, message, wParam, lParam)); + } + + case WM_SIZE: + + MoveWindows(); + + return TRUE; + + case WM_SIZING: + + lprc = (LPRECT) lParam; + + Height = lprc->bottom-lprc->top; + Width = lprc->right-lprc->left; + +#pragma warning(push) +#pragma warning(disable:4244) + SplitPos=Height*Split; +#pragma warning(pop) + + MoveWindows(); + + return TRUE; + + + case WM_DESTROY: + + // Remove the subclass from the edit control. + + GetWindowRect(hWnd, &Rect); // For save soutine + + SetWindowLong(hwndInput, -4, + (LONG) wpOrigInputProc); + + PostQuitMessage(0); + + + break; + + default: + return (DefWindowProc(hWnd, message, wParam, lParam)); + + } + return (0); +} + +static TCHAR * KbdStack[20]; + +int StackIndex=0; + +LRESULT APIENTRY InputProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + TCHAR DisplayLine[250] = L""; + + if (uMsg == WM_CTLCOLOREDIT) + { + HBRUSH Brush = CreateSolidBrush(RGB(0, 255, 0)); + HDC hdcStatic = (HDC)wParam; + SetTextColor(hdcStatic, RGB(0, 0, 0)); + SetBkMode(hdcStatic, TRANSPARENT); + + return (LONG)Brush; + } + + + if (uMsg == WM_KEYUP) + { + unsigned int i; + +// Debugprintf("5%x", LOBYTE(HIWORD(lParam))); + + if (LOBYTE(HIWORD(lParam)) == 0x48 && wParam == 0x26) + { + // Scroll up + + if (KbdStack[StackIndex] == NULL) + return TRUE; + + SendMessage(hwndInput, WM_SETTEXT,0,(LPARAM)(LPCSTR) KbdStack[StackIndex]); + + for (i = 0; i < wcslen(KbdStack[StackIndex]); i++) + { + SendMessage(hwndInput, WM_KEYDOWN, VK_RIGHT, 0); + SendMessage(hwndInput, WM_KEYUP, VK_RIGHT, 0); + } + + StackIndex++; + if (StackIndex == 20) + StackIndex = 19; + + return TRUE; + } + + if (LOBYTE(HIWORD(lParam)) == 0x50 && wParam == 0x28) + { + // Scroll up + + StackIndex--; + if (StackIndex < 0) + StackIndex = 0; + + if (KbdStack[StackIndex] == NULL) + return TRUE; + + SendMessage(hwndInput,WM_SETTEXT,0,(LPARAM)(LPCSTR) KbdStack[StackIndex]); + + for (i = 0; i < wcslen(KbdStack[StackIndex]); i++) + { + SendMessage(hwndInput, WM_KEYDOWN, VK_RIGHT, 0); + SendMessage(hwndInput, WM_KEYUP, VK_RIGHT, 0); + } + + return TRUE; + } + } + + if (uMsg == WM_CHAR) + { + if (wParam == 13) + { + int i; + + if (!Connected && ! Connecting) + { + TCPConnect(Host[CurrentHost], Port[CurrentHost]); + SendMessage(hwndInput,WM_SETTEXT,0,(LPARAM)(LPCSTR) L""); + return 0; + } + + kbptr=SendMessage(hwndInput,WM_GETTEXT,199,(LPARAM) (LPCSTR) kbbuf); + + // Stack it + + StackIndex = 0; + + if (KbdStack[19]) + free(KbdStack[19]); + + for (i = 18; i >= 0; i--) + { + KbdStack[i+1] = KbdStack[i]; + } + + KbdStack[0] = _wcsdup(kbbuf); + + kbbuf[kbptr]=13; + + SlowTimer = 0; + + // Echo, with set Black escape + + DisplayLine[0] = 0x1b; + DisplayLine[1] = 0x21; + + memcpy(&DisplayLine[2], kbbuf, (kbptr+1) * 2); + + if (OutputData.Scrolled) + { + POINT Point; + Point.x = 0; + Point.y = 25000; // Should be plenty for any font + + SendMessage(hwndOutput, EM_SETSCROLLPOS, 0, (LPARAM) &Point); + OutputData.Scrolled = FALSE; + } + + LastWrite = time(NULL); + + WritetoOutputWindow(&OutputData, DisplayLine, kbptr+3); + DoRefresh(&OutputData); + + // Replace null with CR, and send to Node + + SendMsg(&kbbuf[0], kbptr+1); + + SendMessage(hwndInput,WM_SETTEXT,0,(LPARAM)(LPCSTR) L""); + + return 0; + } + if (wParam == 0x1a) // Ctrl/Z + { + kbbuf[0]=0x1a; + kbbuf[1]=13; + + SendMsg(&kbbuf[0], 2); + + SendMessage(hwndInput,WM_SETTEXT,0,(LPARAM)(LPCSTR) L""); + + return 0; + } + } + return CallWindowProc(wpOrigInputProc, hwnd, uMsg, wParam, lParam); +} + +//int FirstItem=-1, LastItem=-1, SELECTING=FALSE, MOVED=FALSE, LastSelected=0; + +LRESULT APIENTRY MonProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST) + return TRUE; + + return CallWindowProc(wpOrigMonProc, hwnd, uMsg, wParam, lParam); +} + +LRESULT APIENTRY SplitProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + int xPos, yPos; + + switch (uMsg) { + + case WM_LBUTTONDOWN: + + SetCapture(hwnd); + return 0; + + case WM_LBUTTONUP: + + xPos = LOWORD(lParam); // horizontal position of cursor + yPos = lParam >> 16; // vertical position of cursor + + SplitPos = SplitPos + yPos - 5; + + if (SplitPos < 0) SplitPos = 0; + + Split=SplitPos; + Split=Split/Height; + + ReleaseCapture(); + MoveWindows(); + DoRefresh(&OutputData); + return 0; + + case WM_MOUSEMOVE: + + // Used to size split between Monitor and Output Windows + + SetCursor(DragCursor); + break; + } + + return CallWindowProc(wpOrigSplitProc, hwnd, uMsg, wParam, lParam); +} + +VOID wcstoRTF(char * out, TCHAR * in) +{ + TCHAR * ptr1 = in; + char * ptr2 = out; + int val = *ptr1++; + + while (val) + { + { + if (val > 127 || val < -128 ) + ptr2 += sprintf(ptr2, "\\u%d ", val); + else + *(ptr2++) = val; + } + val = *ptr1++; + } + *ptr2 = 0; +} + +DWORD CALLBACK EditStreamCallback(DWORD_PTR Cookie, unsigned char * lpBuff, LONG cb, PLONG pcb) +{ + struct RTFTerm * OPData = (struct RTFTerm *)Cookie; + int ReqLen = cb; + int i; + int Line; + char LineB[20000]; + +// if (cb != 4092) +// return 0; + + if (OPData->SendHeader) + { + // Return header + + memcpy(lpBuff, RTFHeader, RTFHddrLen); + *pcb = RTFHddrLen; + OPData->SendHeader = FALSE; + OPData->Finished = FALSE; + OPData->Index = 0; + return 0; + } + + if (OPData->Finished) + { + *pcb = 0; + return 0; + } + +/* + if (BufferLen > cb) + { + memcpy(lpBuff, &Buffer[Offset], cb); + BufferLen -= cb; + Offset += cb; + *pcb = cb; + return 0; + } + + memcpy(lpBuff, &Buffer[Offset], BufferLen); + + *pcb = BufferLen; +*/ + + // Return 10 line at a time + + for (i = 0; i < 10; i++); + { + Line = OPData->Index++ + OPData->CurrentLine - MAXLINES; + + if (Line <0) + Line = Line + MAXLINES; + + wcstoRTF(LineB, OPData->OutputScreen[Line]); + + sprintf(lpBuff, "\\cf%d ", OPData->Colourvalue[Line]); + strcat(lpBuff, LineB); + strcat(lpBuff, "\\line"); + + if (OPData->Index == MAXLINES) + { + OPData->Finished = TRUE; + strcat(lpBuff, "}"); + i = 10; + } + } + *pcb = strlen(lpBuff); + return 0; +} + +VOID ForceRefresh(struct RTFTerm * OPData) +{ + OPData->Thumb = 25000; + DoRefresh(OPData); + OPData->Thumb = SendMessage(hwndOutput, EM_GETTHUMB, 0, 0); +} + +VOID DoRefresh(struct RTFTerm * OPData) +{ + EDITSTREAM es = {0}; + int Min, Max, Pos; + POINT Point; + SCROLLINFO ScrollInfo; + int LoopTrap = 0; + + if(WINE) + OPData->Thumb = 30000; + else + OPData->Thumb = SendMessage(hwndOutput, EM_GETTHUMB, 0, 0); + + Pos = OPData->Thumb + OutputBoxHeight; + + if (Pos > OPData->RTFHeight - 10) // Don't bother writing to screen if scrolled back + { + es.pfnCallback = EditStreamCallback; + es.dwCookie = (DWORD_PTR)OPData; + OPData->SendHeader = TRUE; + SendMessage(hwndOutput, EM_STREAMIN, SF_RTF, (LPARAM)&es); + } +// else +// Debugprintf("Pos %d RTFHeight %d - Not refreshing", Pos, OPData->RTFHeight); + + GetScrollRange(hwndOutput, SB_VERT, &Min, &Max); + ScrollInfo.cbSize = sizeof(ScrollInfo); + ScrollInfo.fMask = SIF_ALL; + + GetScrollInfo(hwndOutput, SB_VERT, &ScrollInfo); + +// Debugprintf("Thumb %d Pos %d Min %d Max %d nMax %d ClientH %d RTFHeight %d", +// OPData->Thumb, Pos, Min, Max, ScrollInfo.nMax, OutputBoxHeight, OPData->RTFHeight); + + if (OPData->FirstTime == FALSE) + { + // RTF Controls don't immediately scroll to end - don't know why. + + OPData->FirstTime = TRUE; + Point.x = 0; + Point.y = 25000; // Should be plenty for any font + + while (LoopTrap++ < 20) + { + SendMessage(hwndOutput, EM_SETSCROLLPOS, 0, (LPARAM) &Point); + } + + GetScrollRange(hwndOutput, SB_VERT, &Min, &Max); // Get Actual Height + OPData->RTFHeight = Max; + Point.x = 0; + Point.y = OPData->RTFHeight - ScrollInfo.nPage; + SendMessage(hwndOutput, EM_SETSCROLLPOS, 0, (LPARAM) &Point); + OPData->Thumb = SendMessage(hwndOutput, EM_GETTHUMB, 0, 0); + } + + Point.x = 0; + Point.y = OPData->RTFHeight - ScrollInfo.nPage; + + if (OPData->Thumb > (Point.y - 10)) // Don't Scroll if user has scrolled back + { +// Debugprintf("Scrolling to %d", Point.y); + SendMessage(hwndOutput, EM_SETSCROLLPOS, 0, (LPARAM) &Point); + if (OPData->Scrolled) + { + OPData->Scrolled = FALSE; + InvalidateRect(hwndInput, NULL, TRUE); + } + return; + } + +// Debugprintf("Thumb = %d Point.y = %d - Not Scrolling", OPData->Thumb, Point.y); + + if (!OPData->Scrolled) + { + OPData->Scrolled = TRUE; + InvalidateRect(hwndInput, NULL, TRUE); + } +} + +VOID AddLinetoWindow(struct RTFTerm * OPData, TCHAR * Line) +{ + int Len = wcslen(Line); + TCHAR * ptr1 = Line; + TCHAR * ptr2; + int l, Index; + TCHAR LineCopy[LINELEN * 2]; + + if (Line[0] == 0x1b && Len > 1) + { + // Save Colour Char + + OPData->CurrentColour = Line[1] - 10; + ptr1 +=2; + Len -= 2; + } + + wcscpy(OPData->OutputScreen[OPData->CurrentLine], ptr1); + + // Look for chars we need to escape (\ { }) + + ptr1 = OPData->OutputScreen[OPData->CurrentLine]; + Index = 0; + ptr2 = wcschr(ptr1, L'\\'); // Look for Backslash first, as we may add some later + + if (ptr2) + { + while (ptr2) + { + l = ++ptr2 - ptr1; + memcpy(&LineCopy[Index], ptr1, l * 2); // Copy Including found char (\) + Index += l; + LineCopy[Index++] = L'\\'; // Add second \ + Len++; + ptr1 = ptr2; + ptr2 = wcschr(ptr1, L'\\'); + } + + wcscpy(&LineCopy[Index], ptr1); // Copy in rest + wcscpy(OPData->OutputScreen[OPData->CurrentLine], LineCopy); + } + + ptr1 = OPData->OutputScreen[OPData->CurrentLine]; + Index = 0; + ptr2 = wcschr(ptr1, L'{'); + + if (ptr2) + { + while (ptr2) + { + l = ptr2 - ptr1; + memcpy(&LineCopy[Index], ptr1, l * 2); + Index += l; + LineCopy[Index++] = L'\\'; + LineCopy[Index++] = L'{'; + Len++; + ptr1 = ++ptr2; + ptr2 = wcschr(ptr1, L'{'); + } + wcscpy(&LineCopy[Index], ptr1); // Copy in rest + wcscpy(OPData->OutputScreen[OPData->CurrentLine], LineCopy); + } + + ptr1 = OPData->OutputScreen[OPData->CurrentLine]; + Index = 0; + ptr2 = wcschr(ptr1, '}'); // Look for Backslash first, as we may add some later + + if (ptr2) + { + while (ptr2) + { + l = ptr2 - ptr1; + memcpy(&LineCopy[Index], ptr1, l * 2); // Copy + Index += l; + LineCopy[Index++] = L'\\'; + LineCopy[Index++] = L'}'; + Len++; + ptr1 = ++ptr2; + ptr2 = wcschr(ptr1, L'}'); + } + wcscpy(&LineCopy[Index], ptr1); // Copy in rest + wcscpy(OPData->OutputScreen[OPData->CurrentLine], LineCopy); + } + + + OPData->Colourvalue[OPData->CurrentLine] = OPData->CurrentColour; + OPData->LineLen[OPData->CurrentLine++] = Len; + if (OPData->CurrentLine >= MAXLINES) OPData->CurrentLine = 0; +} + +VOID WritetoOutputWindow(struct RTFTerm * OPData, TCHAR * Msg, int len) +{ + time_t NOW = time(NULL); + TCHAR * ptr1, * ptr2; + + if (AlertInterval && (NOW - LastWrite) > AlertInterval) + { + if (AlertBeep) + Beep(AlertFreq, AlertDuration); + else + PlaySound(AlertFileName, NULL, SND_FILENAME | SND_ASYNC); + } + + + LastWrite = NOW; + + if (PartLinePtr != 0) + { + OPData->CurrentLine--; // Overwrite part line in buffer + if (OPData->CurrentLine < 0) + OPData->CurrentLine = MAXLINES - 1; + + if (Msg[0] == 0x1b && len > 1) + { + Msg += 2; // Remove Colour Escape + len -= 2; + } + } + + memcpy(&readbuff[PartLinePtr], Msg, len * 2); + + len += PartLinePtr; + + ptr1=&readbuff[0]; + readbuff[len]=0; + + if (Bells) + { + do { + ptr2 = wmemchr(ptr1,7,len); + + if (ptr2) + { + *(ptr2)=32; + Beep(440,250); + } + } while (ptr2); + } + +lineloop: + + if (len > 0) + { + // copy text to buffer a line at a time + + ptr2=wmemchr(ptr1, 13, len); + + if (ptr2 == 0) + { + // no newline. Move data to start of buffer and Save pointer + + while (len > LINELEN) + { + // Break up + + TCHAR * partptr = ptr1 + LINELEN; + TCHAR Save = *partptr; + *ptr1 = 0; + AddLinetoWindow(OPData, ptr1); + *partptr = Save; + ptr1 = partptr; + len -= LINELEN; + } + + PartLinePtr = len; + memmove(readbuff, ptr1, len * 2); + AddLinetoWindow(OPData, ptr1); + return; + } + + *(ptr2++)=0; + + if (LogOutput) WriteMonitorLine(ptr1, ptr2 - ptr1); + + // If len is greater that screen with, fold + + if ((ptr2 - ptr1) > maxlinelen) + { + TCHAR * ptr3; + TCHAR * saveptr1 = ptr1; + int linelen = ptr2 - ptr1; + int foldlen; + TCHAR save; + + foldloop: + + ptr3 = ptr1 + maxlinelen; + + while(*ptr3!= 0x20 && ptr3 > ptr1) + { + ptr3--; + } + foldlen = ptr3 - ptr1 ; + + if (foldlen == 0) + { + // No space before, so split at width + + foldlen = maxlinelen; + ptr3 = ptr1 + maxlinelen; + + } + else + { + ptr3++ ; // Omit space + linelen--; + } + save = ptr1[foldlen]; + ptr1[foldlen] = 0; + + AddLinetoWindow(OPData, ptr1); + + ptr1[foldlen] = save; + linelen -= foldlen; + ptr1 = ptr3; + + if (linelen > maxlinelen) + goto foldloop; + + AddLinetoWindow(OPData, ptr1); + ptr1 = saveptr1; + + } + else + AddLinetoWindow(OPData, ptr1); + + + PartLinePtr=0; + + len-=(ptr2-ptr1); + + ptr1=ptr2; + + if ((len > 0) && StripLF) + { + if (*ptr1 == 0x0a) // Line Feed + { + ptr1++; + len--; + } + } + goto lineloop; + } +} + + + +TCHAR MonSave[2000]; +int MonSaveLen; + +VOID WritetoMonWindow(TCHAR * Msg, int len) +{ + TCHAR * ptr1 = Msg, * ptr2; + int index; + + if (MonSaveLen) + { + // Have part line - append to it + memcpy(&MonSave[MonSaveLen], Msg, len * 2); + MonSaveLen += len; + ptr1 = MonSave; + len = MonSaveLen; + MonSaveLen = 0; + } + +lineloop: + + if (len <= 0) + return; + + // copy text to control a line at a time + + ptr2 = wmemchr(ptr1,13,len); + + if (ptr2 == 0) // No CR + { + memmove(MonSave, ptr1, len * 2); + MonSaveLen = len; + return; + } + + *(ptr2++) = 0; + + index = SendMessage(hwndMon, LB_ADDSTRING, 0, (LPARAM)(LPCTSTR) ptr1 ); + + if (LogMonitor) WriteMonitorLine(ptr1, ptr2 - ptr1); + + if (index > 1200) + do {index=SendMessage(hwndMon,LB_DELETESTRING, 0, 0);} while (index > 1000); + + SendMessage(hwndMon,LB_SETCARETINDEX,(WPARAM) index, MAKELPARAM(FALSE, 0)); + + len -= (ptr2 - ptr1); + ptr1 = ptr2; + + goto lineloop; +} + +VOID DisableConnectMenu(HWND hWnd) +{ + int n; + + for (n = 0; n < MAXHOSTS; n++) + EnableMenuItem(GetMenu(hWnd), BPQCONNECT1 + n, MF_GRAYED); + + DrawMenuBar(hWnd); +} + +VOID DisableDisconnectMenu(HWND hWnd) +{ + EnableMenuItem(GetMenu(hWnd), BPQDISCONNECT, MF_GRAYED); + DrawMenuBar(hWnd); +} + +VOID DisableYAPPMenu(HWND hWnd) +{ + EnableMenuItem(GetMenu(hWnd), YAPPSEND, MF_GRAYED); + DrawMenuBar(hWnd); +} + +VOID EnableYAPPMenu(HWND hWnd) +{ + EnableMenuItem(GetMenu(hWnd), YAPPSEND, MF_ENABLED); + DrawMenuBar(hWnd); +} + + + +VOID EnableConnectMenu(HWND hWnd) +{ + HMENU hMenu; // handle of menu + int n; + + hMenu=GetMenu(hWnd); + + for (n = 0; n < MAXHOSTS; n++) + EnableMenuItem(hMenu, BPQCONNECT1 + n, MF_ENABLED); + + DrawMenuBar(hWnd); +} + +VOID EnableDisconnectMenu(HWND hWnd) +{ + EnableMenuItem(GetMenu(hWnd), BPQDISCONNECT, MF_ENABLED); + DrawMenuBar(hWnd); +} + + +int TogglePort(HWND hWnd, int Item, int mask) +{ + portmask ^= mask; + + if (portmask & mask) + CheckMenuItem(hMenu,Item,MF_CHECKED); + else + CheckMenuItem(hMenu,Item,MF_UNCHECKED); + + SendTraceOptions(); + + return (0); + +} +int ToggleMTX(HWND hWnd) +{ + mtxparam = mtxparam ^ 1; + CheckMenuItem(hMenu, BPQMTX, (mtxparam) ? MF_CHECKED : MF_UNCHECKED); + SendTraceOptions(); + + return (0); + +} +int ToggleMCOM(HWND hWnd) +{ + mcomparam = mcomparam ^ 1; + CheckMenuItem(hMenu, BPQMCOM, (mcomparam) ? MF_CHECKED : MF_UNCHECKED); + SendTraceOptions(); + + return (0); + +} +int ToggleMUI(HWND hWnd) +{ + monUI = monUI ^ 1; + CheckMenuItem(hMenu, MUIONLY, (monUI) ? MF_CHECKED : MF_UNCHECKED); + SendTraceOptions(); + + return (0); + +} +int ToggleParam(HWND hWnd, BOOL * Param, int Item) +{ + *Param = !(*Param); + + CheckMenuItem(hMenu,Item, (*Param) ? MF_CHECKED : MF_UNCHECKED); + + return (0); +} + +void MoveWindows() +{ + RECT rcMain, rcClient; + int ClientHeight, ClientWidth; + + GetWindowRect(hWnd, &rcMain); + GetClientRect(hWnd, &rcClient); + + ClientHeight = rcClient.bottom; + ClientWidth = rcClient.right; + + if (ClientWidth == 0) // Minimized + return; + + OutputBoxHeight = ClientHeight - SplitPos - InputBoxHeight - SplitBarHeight - SplitBarHeight; + + MoveWindow(hwndMon,2, 0, ClientWidth-4, SplitPos, TRUE); + MoveWindow(hwndOutput,2, SplitPos+SplitBarHeight, ClientWidth-4, OutputBoxHeight, TRUE); + MoveWindow(hwndInput,2, ClientHeight-InputBoxHeight-2, ClientWidth-4, InputBoxHeight, TRUE); + MoveWindow(hwndSplit,0, SplitPos, ClientWidth, SplitBarHeight, TRUE); + + GetClientRect(hwndOutput, &rcClient); + + ClientHeight = rcClient.bottom; + ClientWidth = rcClient.right; + + if (ClientWidth > 16) + maxlinelen = ClientWidth/OutputData.CharWidth - 1; + + InvalidateRect(hWnd, NULL, TRUE); +} + +void CopyRichTextToClipboard(HWND hWnd) +{ + int len=0; + HGLOBAL hMem; + char * ptr; + + // Copy Rich Text to Clipboard + + len = SendMessage(hwndOutput, WM_GETTEXTLENGTH, 0, 0); + + hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (len + 1)*2); + + if (hMem != 0) + { + ptr=GlobalLock(hMem); + + if (OpenClipboard(MainWnd)) + { + len = SendMessage(hwndOutput, WM_GETTEXT , len, (LPARAM)ptr); + + GlobalUnlock(hMem); + EmptyClipboard(); + SetClipboardData(CF_UNICODETEXT,hMem); + CloseClipboard(); + } + } + else + GlobalFree(hMem); +} + + +void CopyListToClipboard(HWND hWnd) +{ + int i,n, len=0; + HGLOBAL hMem; + char * ptr; + // + // Copy List Box to clipboard + // + + n = SendMessage(hWnd, LB_GETCOUNT, 0, 0); + + for (i=0; iai_family, res->ai_socktype, res->ai_protocol); + + WSAAsyncSelect(sock, hWnd, WSA_DATA, + FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE); + +/* + + // Resolve Name if needed + + destaddr.sin_family = AF_INET; + destaddr.sin_port = htons(Port); + destaddr.sin_addr.s_addr = inet_addr(Host); + + if (destaddr.sin_addr.s_addr == INADDR_NONE) + { + struct hostent * HostEnt; + + // Resolve name to address + + wsprintf(Title,"BPQTermTCP Version %s - Resolving %s", VersionString, Host); + SetWindowText(hWnd,Title); + + HostEnt = gethostbyname(Host); + + if (!HostEnt) + { + MessageBox(NULL, "Resolve HostName Failed", "BPQTermTCP", MB_OK); + wsprintf(Title,"BPQTermTCP Version %s - Disconnected", VersionString); + SetWindowText(hWnd,Title); + + return FALSE; // Resolve failed + } + + i = 0; + + memcpy(&destaddr.sin_addr.s_addr, HostEnt->h_addr, 4); + } + + ioctlsocket (sock, FIONBIO, ¶m); + + setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)&bcopt,4); + + sinx.sin_family = AF_INET; + sinx.sin_addr.s_addr = INADDR_ANY; + sinx.sin_port = 0; + + if (bind(sock, (LPSOCKADDR) &sinx, addrlen) != 0 ) + { + MessageBox(NULL, "Bind Failed", "BPQTermTCP", MB_OK); + return FALSE; + } +*/ + if ((status = WSAAsyncSelect(sock, hWnd, WSA_CONNECT, FD_CONNECT)) > 0) + { + closesocket(sock); + return FALSE; + } + + if (connect(sock, res->ai_addr, res->ai_addrlen) == 0) + { + // + // Connected successful + // + + return TRUE; + } + else + { + err=WSAGetLastError(); + + if (err == WSAEWOULDBLOCK) + { + // Connect in Progress + + wsprintf(Title,L"BPQTermTCP Version %s - Connecting to %s", VersionStringW, Host); + SetWindowText(hWnd,Title); + + EnableDisconnectMenu(hWnd); + DisableConnectMenu(hWnd); + + return TRUE; + } + else + { + // Connect failed + + closesocket(sock); + MessageBox(NULL, L"Connect Failed", L"BPQTermTCP", MB_OK); + return FALSE; + } + } + return FALSE; +} + +int Telnet_Connected(SOCKET sock, int Error) +{ + TCHAR Msg[80]; + int Len; + int i = 1; + BOOL bcopt = TRUE; + + // Connect Complete + + if (Error) + { + closesocket(sock); + Connecting = FALSE; + SocketActive = FALSE; + + wsprintf(Title,L"BPQTermTCP Version %s - Disconnected", VersionStringW); + SetWindowText(hWnd,Title); + DisableDisconnectMenu(hWnd); + DisableYAPPMenu(hWnd); + EnableConnectMenu(hWnd); + + wsprintf(Msg, L"Connect Failed - Error %d\r", Error); + MessageBox(NULL, Msg, L"BPQTermTCP", MB_OK); + + return 0; + + } + + WSAAsyncSelect(sock, hWnd, WSA_DATA, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE); + + SocketActive = TRUE; + Connecting = FALSE; + Connected = TRUE; + InputMode = 0; + + // Reset Monitor Menu + + // Remove old menu + + while (i) + { + i = RemoveMenu(hPopMenu1, 6, MF_BYPOSITION); + } + + for (i = 1; i <= MonPorts; i++) + { + wsprintf(Msg,L"Port %d",i); + + if (portmask & ((uint64_t)1<<(i-1))) + { + AppendMenu(hPopMenu1,MF_STRING | MF_CHECKED,BPQBASE + i, &Msg[0]); + portmask |= ((uint64_t)1<<(i-1)); + } + else + AppendMenu(hPopMenu1,MF_STRING | MF_UNCHECKED,BPQBASE + i, &Msg[0]); + } + + + Len = wsprintf(Msg, L"%s\r%s\rBPQTermTCP\r", UserName[CurrentHost], Password[CurrentHost]); + + SendMsg(Msg, Len); + + SendTraceOptions(); + + SlowTimer = 0; + + wsprintf(Title, L"BPQTermTCP Version %s - Connected to %s", VersionStringW, Host[CurrentHost]); + SetWindowText(hWnd,Title); + DisableConnectMenu(hWnd); + EnableDisconnectMenu(hWnd); + EnableYAPPMenu(hWnd); + + return 0; +} + +VOID Socket_Accept(int SocketId, int error, int eventcode) +{ + int i = 1, addrlen = sizeof(struct sockaddr_in6); + struct sockaddr_in sin; + unsigned char work[4]; + + u_long param=1; + + sock = accept(SocketId, (struct sockaddr *)&sin, &addrlen); + + WSAAsyncSelect(sock, hWnd, WSA_DATA, FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE); + + SocketActive = TRUE; + Connecting = FALSE; + Connected = TRUE; + + // Reset Monitor Menu + + // Remove old menu + + while (i) + { + i = RemoveMenu(hPopMenu1, 6, MF_BYPOSITION); + } + +// Len = wsprintf(Msg, L"Connected to BPQTermTCP\r"); +// SendMsg(Msg, Len); + +// SendTraceOptions(); + + SlowTimer = 0; + + memcpy(work, &sin.sin_addr.s_addr, 4); + wsprintf(Title, L"BPQTermTCP Version %s - Incoming Connection from %d.%d.%d.%d", VersionStringW, work[0], work[1], work[2], work[3]); + SetWindowText(hWnd,Title); + DisableConnectMenu(hWnd); + EnableDisconnectMenu(hWnd); + + if (AlertFileName[0]) + PlaySound(AlertFileName, NULL, SND_FILENAME | SND_ASYNC); + else + Beep(AlertFreq, AlertDuration); + + return; +} + + + +VOID Socket_Data(int sock, int error, int eventcode) +{ + TCHAR Title[100]; + + switch (eventcode) + { + case FD_READ: + + DataSocket_Read(sock); + return; + + case FD_WRITE: + case FD_OOB: + case FD_ACCEPT: + case FD_CONNECT: + + return; + + case FD_CLOSE: + + if (SocketActive) + closesocket(sock); + + if (ListenOn) + wsprintf(Title, L"BPQTermTCP Version %s Listening for Calls", VersionStringW); + else + wsprintf(Title, L"BPQTermTCP Version %s - Disconnected", VersionStringW); + + SetWindowText(hWnd,Title); + DisableDisconnectMenu(hWnd); + DisableYAPPMenu(hWnd); + + if (ListenOn == 0) + EnableConnectMenu(hWnd); + + WritetoOutputWindow(&OutputData, L"*** Disconnected\r", 17); + DoRefresh(&OutputData); + SocketActive = FALSE; + Connected = FALSE; + Disconnecting = FALSE; + return ; + } + return ; +} +int TrytoGuessCode(unsigned char * Char, int Len) +{ + int Above127 = 0; + int LineDraw = 0; + int NumericAndSpaces = 0; + int n; + + for (n = 0; n < Len; n++) + { + if (Char[n] < 65) + { + NumericAndSpaces++; + } + else + { + if (Char[n] > 127) + { + Above127++; + if (Char[n] > 178 && Char[n] < 219) + { + LineDraw++; + } + } + } + } + + if (Above127 == 0) // DOesn't really matter! + return CP1252; + + if (Above127 == LineDraw) + return CP437; // If only Line Draw chars, assume line draw + + // If mainly below 128, it is probably Latin if mainly above, probably Cyrillic + + if ((Len - (NumericAndSpaces + Above127)) < Above127) + return CP1251; + else + return CP1252; +} + +VOID DataSocket_Read(SOCKET sock) +{ + int len = 0, MonLen, wlen, err = 0, newlen; + unsigned char Buffer[2000]; + UCHAR * ptr; + UCHAR * Buffptr; + UCHAR * FEptr = 0; + TCHAR BufferW[2000]; + + ioctlsocket(sock, FIONREAD, &len); + + if (len > 2000) len = 2000; + + len = recv(sock, Buffer, len, 0); + + if (len == SOCKET_ERROR || len == 0) + { + // Failed or closed - clear connection + + return; + } + + if (InputMode == 'Y') // Yapp + { + ProcessYAPPMessage(Buffer, len); + return; + } + +// mbstowcs(Buffer, BufferB, len); + + // Look for MON delimiters (FF/FE) + + Buffptr = Buffer; + + if (MonData) + { + // Already in MON State + + FEptr = memchr(Buffptr, 0xfe, len); + + if (!FEptr) + { + // no FE - so send all to monitor + + len = MultiByteToWideChar(CP_UTF8, 0, Buffptr, len, BufferW, 2000); + + if (len == 0) + return; + + WritetoMonWindow(BufferW, len); + return; + } + + MonData = FALSE; + + MonLen = FEptr - Buffptr; // Mon Data, Excluding the FE + + wlen = MultiByteToWideChar(CP_UTF8, 0, Buffptr, MonLen, BufferW, 2000); + + if (wlen == 0) + return; + + WritetoMonWindow(BufferW, wlen); + + Buffptr = ++FEptr; // Char following FE + + if (++MonLen < len) + { + len -= MonLen; + goto MonLoop; // See if next in MON or Data + } + + // Nothing Left + + DoRefresh(&OutputData); + return ; + } + +MonLoop: + + if (ptr = memchr(Buffptr, 0xff, len)) + { + // Buffer contains Mon Data + + if (ptr > Buffptr) + { + // Some Normal Data before the FF + + int NormLen = ptr - Buffptr; // Before the FF + + if (NormLen == 1 && Buffptr[0] == 0) + { + // Keepalive + } + + else + { + CheckKeyWords(Buffptr, NormLen); + + wlen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, Buffptr, NormLen, BufferW, 2000); + + err = GetLastError(); + + if (err == ERROR_NO_UNICODE_TRANSLATION) + { + // Input isn't UTF 8. if RXMode = AURO, Try to figure out what it is, otherwise convert usong specified mode + + if (RXMode == AUTO) + { + int Table = TrytoGuessCode(Buffptr, NormLen); + + wlen = MultiByteToWideChar(Table, 0, Buffptr, NormLen, BufferW, 2000); + } + else + { + wlen = MultiByteToWideChar(RXMode, 0, Buffptr, NormLen, BufferW, 2000); + } + } + + if (wlen) + WritetoOutputWindow(&OutputData, BufferW, wlen); + } + + len -= NormLen; + Buffptr = ptr; + goto MonLoop; + } + + if (ptr[1] == 0xff) + { + // Port Definition String + + int NumberofPorts = atoi(&ptr[2]); + char *p, *Context; + int i = 1; + TCHAR msg[80]; + TCHAR ID[80]; + int portnum; + + // Remove old menu + + while (i) + { + i = RemoveMenu(hPopMenu1, 6, MF_BYPOSITION); + } + + p = strtok_s(&ptr[2], "|", &Context); + + while(NumberofPorts--) + { + p = strtok_s(NULL, "|", &Context); + if (p == NULL) + break; + + portnum = atoi(p); + mbstowcs(ID, p, strlen(p) +1); + + wsprintf(msg, L"Port %s", ID); + + if (portmask & ((uint64_t)1<<(portnum - 1))) + AppendMenu(hPopMenu1,MF_STRING | MF_CHECKED,BPQBASE + portnum, &msg[0]); + else + AppendMenu(hPopMenu1,MF_STRING | MF_UNCHECKED,BPQBASE + portnum, &msg[0]); + + i++; + } + + return; + } + + + MonData = TRUE; + + FEptr = memchr(Buffptr, 0xfe, len); + + if (FEptr) + { + MonData = FALSE; + + MonLen = FEptr + 1 - Buffptr; // MonLen includes FF and FE + + wlen = MultiByteToWideChar(CP_UTF8, 0, Buffptr + 1, MonLen - 2, BufferW, 2000); + + if (wlen) + WritetoMonWindow(BufferW, wlen); + + DoRefresh(&OutputData); + + len -= MonLen; + Buffptr += MonLen; // Char Following FE + + if (len <= 0) + { + return; + } + goto MonLoop; + } + else + { + // No FE, so rest of buffer is MON Data + + wlen = MultiByteToWideChar(CP_UTF8, 0, Buffptr + 1, MonLen - 1, BufferW, 2000); // Exclude FF + + if (wlen == 0) + return; + + WritetoMonWindow(BufferW, wlen); + return; + } + } + + // No FF, so must be session data + + if (InputMode == 'Y') // Yapp + { + ProcessYAPPMessage(Buffer, len); + return; + } + + + if (len == 1 && Buffptr[0] == 0) + return; // Keepalive + + // Could be a YAPP Header + + + if (len == 2 && Buffptr[0] == ENQ && Buffptr[1] == 1) // YAPP Send_Init + { + UCHAR YAPPRR[2]; + char Mess[64]; + + // Turn off monitoring + + len = sprintf(Mess, "\\\\\\\\%x %x %x %x %x %x %x %x\r", 0, 0, 0, 0, 0, 0, 0, 0); + send(sock, Mess, len, 0); + InputMode = 'Y'; + + YAPPRR[0] = ACK; + YAPPRR[1] = 1; + + Sleep(1000); // To give Monitor Msg time to be sent + QueueMsg(YAPPRR, 2); + + return; + } + + CheckKeyWords(Buffptr, len); + + newlen = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, Buffptr, len, BufferW, 2000); + + err = GetLastError(); + + if (err == ERROR_NO_UNICODE_TRANSLATION) + { + // Input isn't UTF 8. if RXMode = AURO, Try to figure out what it is, otherwise convert usong specified mode + + if (RXMode == AUTO) + { + int Table = TrytoGuessCode(Buffptr, len); + + newlen = MultiByteToWideChar(Table, 0, Buffptr, len, BufferW, 2000); + } + else + { + newlen = MultiByteToWideChar(RXMode, 0, Buffptr, len, BufferW, 2000); + } + } + + if (newlen) + WritetoOutputWindow(&OutputData, BufferW, newlen); + + DoRefresh(&OutputData); + SlowTimer = 0; + return; +} + +int SendMsg(TCHAR * msg, int len) +{ + unsigned char MsgB[1000]; + + len = WideCharToMultiByte(TXMode, 0, msg, len, MsgB, 1000, NULL, NULL); + + send(sock, MsgB, len, 0); + return 0; +} + +VOID SendTraceOptions() +{ + char Buffer[80]; + int Len = sprintf(Buffer, "\\\\\\\\%llx %x %x %x %x %x %x %x\r", portmask, mtxparam, mcomparam, MonitorNODES, MonitorColour, monUI, TXMode == CP_UTF8, 1); + mbstowcs(&MonParams[CurrentHost][0], &Buffer[4], Len - 4); + SaveStringValue(MON[CurrentHost], MonParams[CurrentHost]); + Sleep(1000); // To give YAPP Msg tome to be sent + send(sock, Buffer, Len, 0); + +} + +SOCKET OpenListenSocket4(int port) +{ + struct sockaddr_in local_sin; /* Local socket - internet style */ + struct sockaddr_in * psin; + SOCKET sock = 0; + u_long param=1; + WCHAR Msg[80]; + + psin=&local_sin; + psin->sin_family = AF_INET; + psin->sin_addr.s_addr = INADDR_ANY; + + if (port) + { + sock = socket(AF_INET, SOCK_STREAM, 0); + + if (sock == INVALID_SOCKET) + { + wsprintf(Msg, L"socket() failed error %d", WSAGetLastError()); + MessageBox(NULL, Msg, L"BPQTermTCP", MB_OK); + return 0; + } + + setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (char *)¶m,4); + + psin->sin_port = htons(port); // Convert to network ordering + + if (bind( sock, (struct sockaddr *) &local_sin, sizeof(local_sin)) == SOCKET_ERROR) + { + wsprintf(Msg, L"bind(sock) failed port %d Error %d", port, WSAGetLastError()); + MessageBox(NULL, Msg, L"BPQTermTCP", MB_OK); + closesocket(sock); + return FALSE; + } + + if (listen(sock, 4) < 0) + { + wsprintf(Msg, L"listen(sock) failed port %d Error %d", port, WSAGetLastError()); + MessageBox(NULL, Msg, L"BPQTermTCP", MB_OK); + closesocket(sock); + } + + WSAAsyncSelect(sock, hWnd, WSA_ACCEPT, FD_ACCEPT | FD_CLOSE); + } + return sock; +} + + + +static unsigned int cp1251Map[256] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, '\n', 0x000B, 0x000C, '\r', 0x000E, 0x000F, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, '\'', + 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005A, 0x005B, '\\', 0x005D, 0x005E, 0x005F, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, + 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, + 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, + 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0xFFFD, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, + 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, + 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, + 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, + 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F +}; + +#define INCLUDEYAPP +#ifdef INCLUDEYAPP + + +// YAPP stuff + +#define SOH 1 +#define STX 2 +#define ETX 3 +#define EOT 4 +#define ENQ 5 +#define ACK 6 +#define DLE 0x10 +#define NAK 0x15 +#define CAN 0x18 + +#define YAPPTX 32768 // Sending YAPP file + +int MaxRXSize = 100000; +char BaseDir[256] = ""; + +UCHAR InputBuffer[1024]; + +UCHAR InputMode; // Line by Line or Binary or YAPP +int paclen = 128; + +int InputLen; // Data we have already = Offset of end of an incomplete packet; + +UCHAR * MailBuffer; // Yapp Message being received +int MailBufferSize; +int YAPPLen; // Bytes sent/received of YAPP Message +long YAPPDate; // Date for received file - if set enables YAPPC +char ARQFilename[256]; // Filename from YAPP Header + +UCHAR SavedData[4096]; // Max receive is 2000 is should never get more that 4000 +int SaveLen = 0; + +void YAPPSendData(); + +void QueueMsg(UCHAR * Msg, int Len) +{ + int Sent = send(sock, Msg, Len, 0); + + if (Sent != Len) + Sent = 0; +} + +int InnerProcessYAPPMessage(UCHAR * Msg, int Len); + +BOOL ProcessYAPPMessage(UCHAR * Msg, int Len) +{ + // may have saved data + + memcpy(&SavedData[SaveLen], Msg, Len); + + SaveLen += Len; + + while (SaveLen && InputMode == 'Y') + { + int Used = InnerProcessYAPPMessage(SavedData, SaveLen); + + if (Used == 0) + return 0; // Waiting for more + + SaveLen -= Used; + + if (SaveLen) + memmove(SavedData, &SavedData[Used], SaveLen); + } + return 0; +} + +int InnerProcessYAPPMessage(UCHAR * Msg, int Len) +{ + int pktLen = Msg[1]; + char Reply[2] = {ACK}; + int NameLen, SizeLen, OptLen; + char * ptr; + int FileSize; + WCHAR MsgFile[MAX_PATH]; + FILE * hFile; + char Mess[255]; + int len; + TCHAR BufferW[2000]; + WCHAR WFN[MAX_PATH]; + + switch (Msg[0]) + { + case ENQ: // YAPP Send_Init + + // Shouldn't occur in session. Reset state and process + + if (MailBuffer) + { + free(MailBuffer); + MailBufferSize=0; + MailBuffer=0; + } + + Mess[0] = ACK; + Mess[1] = 1; + + InputMode = 'Y'; + QueueMsg(Mess, 2); + + // Turn off monitoring + + Sleep(1000); // To give YAPP Msg tome to be sent + + len = sprintf(Mess, "\\\\\\\\%x %x %x %x %x %x %x %x\r", 0, 0, 0, 0, 0, 0, 0, 0); + send(sock, Mess, len, 0); + + return Len; + + case SOH: + + // HD Send_Hdr SOH len (Filename) NUL (File Size in ASCII) NUL (Opt) + + // YAPPC has date/time in dos format + + NameLen = strlen(&Msg[2]); + strcpy(ARQFilename, &Msg[2]); + + // ARQFN normal string. Create WCS copy + + mbstowcs(WFN, ARQFilename, MAX_PATH); + + + ptr = &Msg[3 + NameLen]; + SizeLen = strlen(ptr); + FileSize = atoi(ptr); + + OptLen = pktLen - (NameLen + SizeLen + 2); + + YAPPDate = 0; + + if (OptLen >= 8) // We have a Date/Time for YAPPC + { + ptr = ptr + SizeLen + 1; + YAPPDate = strtol(ptr, NULL, 16); + } + + // Check Size + + if (FileSize > MaxRXSize) + { + Mess[0] = NAK; + Mess[1] = sprintf(&Mess[2], "File %s size %d larger than limit %d\r", WFN, FileSize, MaxRXSize); + Sleep(1000); // To give YAPP Msg tome to be sent + QueueMsg(Mess, Mess[1] + 2); + + len = wsprintf(BufferW, L"YAPP File %s size %d larger than limit %d\r", WFN, FileSize, MaxRXSize); + WritetoOutputWindow(&OutputData, BufferW, len); + DoRefresh(&OutputData); + InputMode = 0; + SendTraceOptions(); + + return Len; + } + + // Make sure file does not exist + + // Path is Wide String, ARQFN normal + + wsprintf(MsgFile, L"%s%s", YAPPPath, WFN); + + hFile = CreateFile(MsgFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) + { + Mess[0] = NAK; + Mess[1] = sprintf(&Mess[2], "%s", "File Already Exists"); + Sleep(1000); // To give YAPP Msg tome to be sent + QueueMsg(Mess, Mess[1] + 2); + len = wsprintf(BufferW, L"YAPP File Receive Failed - %s already exists\r", MsgFile); + WritetoOutputWindow(&OutputData, BufferW, len); + DoRefresh(&OutputData); + + CloseHandle(hFile); + InputMode = 0; + SendTraceOptions(); + + return Len; + } + + + MailBufferSize = FileSize; + MailBuffer = malloc(FileSize); + YAPPLen = 0; + + if (YAPPDate) // If present use YAPPC + Reply[1] = ACK; //Receive_TPK + else + Reply[1] = 2; //Rcv_File + + QueueMsg( Reply, 2); + + len = wsprintf(BufferW, L"YAPP Receving File %s size %d\r", WFN, FileSize); + WritetoOutputWindow(&OutputData, BufferW, len); + DoRefresh(&OutputData); + + + return Len; + + case STX: + + // Data Packet + + // Check we have it all + + if (YAPPDate) // If present use YAPPC so have checksum + { + if (pktLen > (Len - 3)) // -2 for header and checksum + return 0; // Wait for rest + } + else + { + if (pktLen > (Len - 2)) // -2 for header + return 0; // Wait for rest + } + + // Save data and remove from buffer + + // if YAPPC check checksum + + if (YAPPDate) + { + UCHAR Sum = 0; + int i; + UCHAR * uptr = &Msg[2]; + + i = pktLen; + + while(i--) + Sum += *(uptr++); + + if (Sum != *uptr) + { + // Checksum Error + + Mess[0] = CAN; + Mess[1] = sprintf_s(&Mess[2], sizeof(Mess), "YAPPC Checksum Error"); + QueueMsg( Mess, Mess[1] + 2); + + len = wsprintf(BufferW, L"YAPPC Checksum Error\r", MsgFile); + WritetoOutputWindow(&OutputData, BufferW, len); + DoRefresh(&OutputData); + + InputMode = 0; + SendTraceOptions(); + return Len; + } + } + + if ((YAPPLen) + pktLen > MailBufferSize) + { + // Too Big ?? + + Mess[0] = CAN; + Mess[1] = sprintf(&Mess[2], "YAPP Too much data received"); + QueueMsg(Mess, Mess[1] + 2); + + len = wsprintf(BufferW, L"YAPP Too much data received\r", MsgFile); + WritetoOutputWindow(&OutputData, BufferW, len); + DoRefresh(&OutputData); + + InputMode = 0; + SendTraceOptions(); + return Len; + } + + + memcpy(&MailBuffer[YAPPLen], &Msg[2], pktLen); + YAPPLen += pktLen; + + if (YAPPDate) + ++pktLen; // Add Checksum + + return pktLen + 2; + + case ETX: + + // End Data + + if (YAPPLen == MailBufferSize) + { + // All received + + int ret; + DWORD Written = 0; + WCHAR WFN[MAX_PATH]; + + // Path is Wide String, ARQFN normal + + mbstowcs(WFN, ARQFilename, MAX_PATH); + + wsprintf(MsgFile, L"%s%s", YAPPPath, WFN); + +#ifdef WIN32 + hFile = CreateFile(MsgFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + if((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) + { + ret = WriteFile(hFile, MailBuffer, YAPPLen, &Written, NULL); + + if (YAPPDate) + { + FILETIME FileTime; + struct tm TM; + struct timeval times[2]; + time_t TT; +/* + The MS-DOS date. The date is a packed value with the following format. + + cant use DosDateTimeToFileTime on Linux + + Bits Description + 0-4 Day of the month (1–31) + 5-8 Month (1 = January, 2 = February, and so on) + 9-15 Year offset from 1980 (add 1980 to get actual year) + wFatTime + The MS-DOS time. The time is a packed value with the following format. + Bits Description + 0-4 Second divided by 2 + 5-10 Minute (0–59) + 11-15 Hour (0–23 on a 24-hour clock) +*/ + memset(&TM, 0, sizeof(TM)); + + TM.tm_sec = (YAPPDate & 0x1f) << 1; + TM.tm_min = ((YAPPDate >> 5) & 0x3f); + TM.tm_hour = ((YAPPDate >> 11) & 0x1f); + + TM.tm_mday = ((YAPPDate >> 16) & 0x1f); + TM.tm_mon = ((YAPPDate >> 21) & 0xf) - 1; + TM.tm_year = ((YAPPDate >> 25) & 0x7f) + 80; + + Debugprintf("%d %d %d %d %d %d", TM.tm_year, TM.tm_mon, TM.tm_mday, TM.tm_hour, TM.tm_min, TM.tm_sec); + + TT = mktime(&TM); + times[0].tv_sec = times[1].tv_sec = + times[0].tv_usec = times[1].tv_usec = 0; + + DosDateTimeToFileTime((WORD)(YAPPDate >> 16), (WORD)YAPPDate & 0xFFFF, &FileTime); + ret = SetFileTime(hFile, &FileTime, &FileTime, &FileTime); + ret = GetLastError(); + + } + CloseHandle(hFile); + } +#else + + hFile = fopen(MsgFile, "wb"); + if (hFile) + { + Written = fwrite(MailBuffer, 1, YAPPLen, hFile); + fclose(hFile); + + if (YAPPDate) + { + struct tm TM; + struct timeval times[2]; +/* + The MS-DOS date. The date is a packed value with the following format. + + cant use DosDateTimeToFileTime on Linux + + Bits Description + 0-4 Day of the month (1–31) + 5-8 Month (1 = January, 2 = February, and so on) + 9-15 Year offset from 1980 (add 1980 to get actual year) + wFatTime + The MS-DOS time. The time is a packed value with the following format. + Bits Description + 0-4 Second divided by 2 + 5-10 Minute (0–59) + 11-15 Hour (0–23 on a 24-hour clock) +*/ + memset(&TM, 0, sizeof(TM)); + + TM.tm_sec = (YAPPDate & 0x1f) << 1; + TM.tm_min = ((YAPPDate >> 5) & 0x3f); + TM.tm_hour = ((YAPPDate >> 11) & 0x1f); + + TM.tm_mday = ((YAPPDate >> 16) & 0x1f); + TM.tm_mon = ((YAPPDate >> 21) & 0xf) - 1; + TM.tm_year = ((YAPPDate >> 25) & 0x7f) + 80; + + Debugprintf("%d %d %d %d %d %d", TM.tm_year, TM.tm_mon, TM.tm_mday, TM.tm_hour, TM.tm_min, TM.tm_sec); + + times[0].tv_sec = times[1].tv_sec = mktime(&TM); + times[0].tv_usec = times[1].tv_usec = 0; + } + } +#endif + + free(MailBuffer); + MailBufferSize=0; + MailBuffer=0; + + if (Written != YAPPLen) + { + Mess[0] = CAN; + Mess[1] = sprintf_s(&Mess[2], sizeof(Mess), "Failed to save YAPP File"); + QueueMsg(Mess, Mess[1] + 2); + + len = wsprintf(BufferW, L"Failed to save YAPP File\r", MsgFile); + WritetoOutputWindow(&OutputData, BufferW, len); + DoRefresh(&OutputData); + InputMode = 0; + SendTraceOptions(); + } + } + + Reply[1] = 3; //Ack_EOF + QueueMsg( Reply, 2); + + len = wsprintf(BufferW, L"Reception of file %s complete\r", MsgFile); + WritetoOutputWindow(&OutputData, BufferW, len); + DoRefresh(&OutputData); + + + return Len; + + case EOT: + + // End Session + + Reply[1] = 4; // Ack_EOT + QueueMsg( Reply, 2); + InputMode = 0; + + SendTraceOptions(); + return Len; + + case CAN: + + // Abort + + Mess[0] = ACK; + Mess[1] = 5; // CAN Ack + QueueMsg( Mess, 2); + + if (MailBuffer) + { + free(MailBuffer); + MailBufferSize=0; + MailBuffer=0; + } + + // May have an error message + + len = Msg[1]; + + if (len) + { + WCHAR ws[256]; + + Msg[len + 2] = 0; + mbstowcs(ws, &Msg[2], 255); + + len = wsprintf(BufferW, L"YAPP Transfer cancelled - %s\r", ws); + } + else + len = sprintf_s(Mess, sizeof(Mess), "YAPP Transfer cancelled\r"); + + InputMode = 0; + SendTraceOptions(); + + return Len; + + case ACK: + + switch (Msg[1]) + { + char * ptr; + + case 1: // Rcv_Rdy + + // HD Send_Hdr SOH len (Filename) NUL (File Size in ASCII) NUL (Opt) + + // Remote only needs filename so remove path + + ptr = ARQFilename; + + while (strchr(ptr, '\\')) + ptr = strchr(ptr, '\\') + 1; + + len = strlen(ptr) + 3; + + strcpy(&Mess[2], ptr); + len += sprintf(&Mess[len], "%d", MailBufferSize); + len++; // include null + len += sprintf(&Mess[len], "%8X", YAPPDate); + len++; // include null + Mess[0] = SOH; + Mess[1] = len - 2; + + QueueMsg( Mess, len); + + return Len; + + case 2: + + YAPPDate = 0; // Switch to Normal (No Checksum) Mode + + case 6: // Send using YAPPC + + // Start sending message + + YAPPSendData(); + return Len; + + case 3: + + // ACK EOF - Send EOT + + Mess[0] = EOT; + Mess[1] = 1; + QueueMsg( Mess, 2); + + return Len; + + case 4: + + // ACK EOT + + InputMode = 0; + SendTraceOptions(); + + len = wsprintf(BufferW, L"File transfer complete\r"); + WritetoOutputWindow(&OutputData, BufferW, len); + DoRefresh(&OutputData); + + return Len; + + default: + return Len; + + } + + case NAK: + + // Either Reject or Restart + + // RE Resume NAK len R NULL (File size in ASCII) NULL + + if (Len > 2 && Msg[2] == 'R' && Msg[3] == 0) + { + int posn = atoi(&Msg[4]); + + YAPPLen += posn; + MailBufferSize -= posn; + + YAPPSendData(); + return Len; + + } + + // May have an error message + + len = Msg[1]; + + if (len) + { + WCHAR ws[256]; + + Msg[len + 2] = 0; + + mbstowcs(ws, &Msg[2], 255); + + len = wsprintf(BufferW, L"File rejected - %s\r", ws); + } + else + len = wsprintf(BufferW, L"File rejected\r"); + + WritetoOutputWindow(&OutputData, BufferW, len); + DoRefresh(&OutputData); + + InputMode = 0; + SendTraceOptions(); + + return Len; + + } + + len = wsprintf(BufferW, L"Unexpected message during YAPP Transfer. Transfer canncelled\r"); + WritetoOutputWindow(&OutputData, BufferW, len); + DoRefresh(&OutputData); + + InputMode = 0; + SendTraceOptions(); + + return Len; + +} + +void YAPPSendFile(WCHAR * FN) +{ + int FileSize; + char MsgFile[MAX_PATH]; + FILE * hFile; + struct stat STAT; + TCHAR BufferW[2000]; + int Len; + + wcstombs(MsgFile, FN, MAX_PATH); + + if (MsgFile == NULL) + { + Len = wsprintf(BufferW, L"Filename missing\r"); + WritetoOutputWindow(&OutputData, BufferW, Len); + DoRefresh(&OutputData); + SendTraceOptions(); + + return; + } + + if (stat(MsgFile, &STAT) != -1) + { + FileSize = STAT.st_size; + + hFile = fopen(MsgFile, "rb"); + + if (hFile) + { + char Mess[255]; + time_t UnixTime = STAT.st_mtime; + FILETIME ft; + LONGLONG ll; + SYSTEMTIME st; + WORD FatDate; + WORD FatTime; + struct tm TM; + + strcpy(ARQFilename, MsgFile); + MailBuffer = malloc(FileSize); + MailBufferSize = FileSize; + YAPPLen = 0; + fread(MailBuffer, 1, FileSize, hFile); + + // Get Date and Time for YAPPC Mode + +/* The MS-DOS date. The date is a packed value with the following format. + + cant use DosDateTimeToFileTime on Linux + + Bits Description + 0-4 Day of the month (1–31) + 5-8 Month (1 = January, 2 = February, and so on) + 9-15 Year offset from 1980 (add 1980 to get actual year) + wFatTime + The MS-DOS time. The time is a packed value with the following format. + Bits Description + 0-4 Second divided by 2 + 5-10 Minute (0–59) + 11-15 Hour (0–23 on a 24-hour clock) + + memset(&TM, 0, sizeof(TM)); + + TM.tm_sec = (YAPPDate & 0x1f) << 1; + TM.tm_min = ((YAPPDate >> 5) & 0x3f); + TM.tm_hour = ((YAPPDate >> 11) & 0x1f); + + TM.tm_mday = ((YAPPDate >> 16) & 0x1f); + TM.tm_mon = ((YAPPDate >> 21) & 0xf) - 1; + TM.tm_year = ((YAPPDate >> 25) & 0x7f) + 80; +*/ + + // Note that LONGLONG is a 64-bit value + + ll = Int32x32To64(UnixTime, 10000000) + 116444736000000000; + ft.dwLowDateTime = (DWORD)ll; + ll >>= 32; + ft.dwHighDateTime = (DWORD)ll; + + FileTimeToSystemTime(&ft, &st); + FileTimeToDosDateTime(&ft, &FatDate, &FatTime); + + YAPPDate = (FatDate << 16) + FatTime; + + memset(&TM, 0, sizeof(TM)); + + TM.tm_sec = (YAPPDate & 0x1f) << 1; + TM.tm_min = ((YAPPDate >> 5) & 0x3f); + TM.tm_hour = ((YAPPDate >> 11) & 0x1f); + + TM.tm_mday = ((YAPPDate >> 16) & 0x1f); + TM.tm_mon = ((YAPPDate >> 21) & 0xf) - 1; + TM.tm_year = ((YAPPDate >> 25) & 0x7f) + 80; + + fclose(hFile); + + Mess[0] = ENQ; + Mess[1] = 1; + + QueueMsg(Mess, 2); + InputMode = 'Y'; + + return; + } + } + + Len = wsprintf(BufferW, L"File %s not found\r", FN); + WritetoOutputWindow(&OutputData, BufferW, Len); + DoRefresh(&OutputData); +} + +void YAPPSendData() +{ + char Mess[258]; + + while (1) + { + int Left = MailBufferSize; + + if (Left == 0) + { + // Finished - send End Data + + Mess[0] = ETX; + Mess[1] = 1; + + QueueMsg( Mess, 2); + + break; + } + + if (Left > paclen - 3) // two bytes header and possible checksum + Left = paclen - 3; + + memcpy(&Mess[2], &MailBuffer[YAPPLen], Left); + + YAPPLen += Left; + MailBufferSize -= Left; + + // if YAPPC add checksum + + if (YAPPDate) + { + UCHAR Sum = 0; + int i; + UCHAR * uptr = &Mess[2]; + + i = Left; + + while(i--) + Sum += *(uptr++); + + *(uptr) = Sum; + + Mess[0] = STX; + Mess[1] = Left; + + QueueMsg( Mess, Left + 3); + } + else + { + Mess[0] = STX; + Mess[1] = Left; + + QueueMsg( Mess, Left + 2); + } + } +} + +#endif diff --git a/cMain.c b/cMain.c index 6b984b0..62235a7 100644 --- a/cMain.c +++ b/cMain.c @@ -517,6 +517,8 @@ Loop: Session.CIRCUITINDEX = -1; Buffer->LENGTH = sprintf(Buffer->L2DATA, "%s\r", TNC->DisconnectScript[n++]) + (sizeof(void *) + 4); CommandHandler(&Session, Buffer); + strlop(Buffer->L2DATA, 13); + Debugprintf("Disconnect Script Output %s", Buffer->L2DATA); }; } } diff --git a/chatconfig.cfg b/chatconfig.cfg index c990d97..7d23f4f 100644 --- a/chatconfig.cfg +++ b/chatconfig.cfg @@ -18,5 +18,5 @@ Chat : MonitorSize = "828,1644,148,770"; DebugSize = "0,0,0,0"; WindowSize = "231,835,254,602"; - Version = "6,0,24,81"; + Version = "6,0,25,40"; }; diff --git a/debug/bpq32.pdb b/debug/bpq32.pdb new file mode 100644 index 0000000..309e05e Binary files /dev/null and b/debug/bpq32.pdb differ diff --git a/makefile b/makefile index 26403e5..b2bd9db 100644 --- a/makefile +++ b/makefile @@ -22,7 +22,7 @@ OBJS = pngwtran.o pngrtran.o pngset.o pngrio.o pngwio.o pngtrans.o pngrutil.o pn LDFLAGS = -Xlinker -Map=output.map -lrt all: CFLAGS = -DLINBPQ -MMD -g -fcommon -fasynchronous-unwind-tables $(EXTRA_CFLAGS) -all: LIBS = -lpaho-mqtt3a -ljansson -lminiupnpc -lm -lz -lpthread -lconfig -lpcap +all: LIBS = -lpaho-mqtt3a -ljansson -lminiupnpc -lm -lz -lpthread -lconfig -lpcap -lbacktrace all: linbpq #other OS diff --git a/tncinfo.h b/tncinfo.h index eac4b97..003cbd7 100644 --- a/tncinfo.h +++ b/tncinfo.h @@ -193,6 +193,7 @@ struct TCPINFO HWND hCMSWnd; int SecureTelnet; + int noWebSocks; int ReportRelayTraffic; // Send WL2K Reports for Relay Traffic char * WebTermCSS; // css override for web terminal