1
0
Fork 0

import from subversion

master
Bob Carroll 2013-10-17 15:07:31 -07:00
commit 588e118469
24 changed files with 3994 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
.DS_Store
.*.swp
Debug/
Release/
*.user
*.suo
*.filters
WinTN3270.sdf

40
AssemblyInfo.cpp Normal file
View File

@ -0,0 +1,40 @@
#include "stdafx.h"
using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly:AssemblyTitleAttribute("WinTN3270")];
[assembly:AssemblyDescriptionAttribute("")];
[assembly:AssemblyConfigurationAttribute("")];
[assembly:AssemblyCompanyAttribute("NTID")];
[assembly:AssemblyProductAttribute("WinTN3270")];
[assembly:AssemblyCopyrightAttribute("Copyright (c) 2007 Bob Carroll")];
[assembly:AssemblyTrademarkAttribute("")];
[assembly:AssemblyCultureAttribute("")];
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the value or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly:AssemblyVersionAttribute("1.0.*")];
[assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)];
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];

193
C3270Char.cpp Normal file
View File

@ -0,0 +1,193 @@
/***********************************************************
WinTN3270
Copyright © 2007 Bob Carroll (bob.carroll@alum.rit.edu)
This software is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation;
either version 2, or (at your option) any later version.
This software is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public
License along with this software; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301 USA
***********************************************************/
#include "stdafx.h"
#include "C3270Char.h"
#include "CEbcdicTranslator.h"
using namespace WinTN3270;
using namespace System;
using namespace System::Drawing;
/***********************************************************
Creates a NULL character object.
***********************************************************/
C3270Char::C3270Char()
{
this->__Constructor(NULL, false);
}
/***********************************************************
Creates a character object from a byte.
@param chChar the EBCDIC character to use
***********************************************************/
C3270Char::C3270Char(Byte chChar)
{
this->__Constructor(chChar, false);
}
/***********************************************************
Creates a character object from a byte. This is the
start-of-field byte.
@param chChar the EBCDIC character to use
@param fStartField flag to indicate start-of-field
***********************************************************/
C3270Char::C3270Char(Byte chChar, bool fStartField)
{
this->__Constructor(chChar, true);
this->UnserializeAttributes();
}
/***********************************************************
Creates a character object from a byte. This is the real
constructor.
@param chChar the EBCDIC character to use
@param fStartField flag to indicate start-of-field
***********************************************************/
void C3270Char::__Constructor(System::Byte chChar, bool fStartField)
{
m_chChar = (fStartField ? chChar : CEbcdicTranslator::CharToASCII(chChar));
m_chInitChar = m_chChar;
m_fAutoSkip = false;
m_fModified = false;
m_fNumeric = false;
m_fProtected = false;
m_fStartField = fStartField;
m_nDisplay = 0;
}
/***********************************************************
Gets the appropriate color brush.
@return the brush to paint with
***********************************************************/
Brush^ C3270Char::GetPaintBrush()
{
switch (m_nDisplay) {
/* Bright */
case DisplayOptions::Bright:
return Brushes::White;
/* Dark */
case DisplayOptions::Dark:
return Brushes::Black;
/* Normal */
default:
return Brushes::Green;
}
}
/***********************************************************
Gets the appropriate color brush.
@param fBaseColor flag to enable base colors
@return the brush to paint with
***********************************************************/
Brush^ C3270Char::GetPaintBrush(bool fBaseColor)
{
bool fBright = (m_nDisplay == DisplayOptions::Bright);
/* Get the base color */
if (!m_fProtected && !fBright) /* Green */
return Brushes::Green;
else if (!m_fProtected && fBright) /* Red */
return Brushes::Red;
else if (m_fProtected && !fBright) /* Blue */
return Brushes::Blue;
else if (m_fProtected && fBright) /* White */
return Brushes::White;
return this->GetPaintBrush();
}
/***********************************************************
Creates a string representation of the character object.
@return a pretty string
***********************************************************/
String^ C3270Char::ToString()
{
return this->ToString(false);
}
/***********************************************************
Creates a string representation of the character object.
@param fMasked flag to mask the character
@return a pretty string
***********************************************************/
String^ C3270Char::ToString(bool fMasked)
{
/* Null character displays nothing */
if (m_chChar == 0 || m_fStartField)
return " ";
/* Some unprotected fields are dark so we mask the real character */
if (fMasked && m_chChar != m_chInitChar)
return "*";
/* Otherwise output the character array */
array<wchar_t>^ pchString = { m_chChar };
return gcnew String(pchString);
}
/***********************************************************
Reads the field attribute bit field and sets class vars
accordingly.
@param chAttr the attribute byte
***********************************************************/
void C3270Char::UnserializeAttributes()
{
/* Bit 7: Modified Data Tag */
m_fModified = (m_chChar & 0x01);
/* Bit 6: Reserved, always zero */
/* Bits 4-5: Field Display */
if ((m_chChar >> 2 & 0x03) == 0x00)
m_nDisplay = DisplayOptions::NormalNoLPDetect;
else if ((m_chChar >> 2 & 0x03) == 0x01)
m_nDisplay = DisplayOptions::NormalLPDetect;
else if ((m_chChar >> 2 & 0x03) == 0x02)
m_nDisplay = DisplayOptions::Bright;
else if ((m_chChar >> 2 & 0x03) == 0x03)
m_nDisplay = DisplayOptions::Dark;
/* Bit 3: Numeric Only */
m_fNumeric = (m_chChar >> 4 & 0x01);
/* Bit 2: Protected */
m_fProtected = (m_chChar >> 5 & 0x01);
if (m_fNumeric && m_fProtected)
m_fAutoSkip = true;
/* Bit 1: Unknown (Ignored) */
/* Bit 0: Unknown (Ignored) */
}

138
C3270Char.h Normal file
View File

@ -0,0 +1,138 @@
/***********************************************************
WinTN3270
Copyright © 2007 Bob Carroll (bob.carroll@alum.rit.edu)
This software is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation;
either version 2, or (at your option) any later version.
This software is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public
License along with this software; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301 USA
***********************************************************/
#pragma once
namespace WinTN3270
{
/***********************************************************
Character object for 3270 terminals.
***********************************************************/
public ref class C3270Char
{
public: /* Public Enums */
ref class DisplayOptions
{
public:
static const int NormalNoLPDetect = 0;
static const int NormalLPDetect = 1;
static const int Bright = 2;
static const int Dark = 3;
};
private: /* Private Member Attributes */
wchar_t m_chInitChar;
wchar_t m_chChar;
bool m_fAutoSkip;
bool m_fModified;
bool m_fNumeric;
bool m_fProtected;
bool m_fStartField;
int m_nDisplay;
public: /* Public Properties */
property bool AutoSkip
{
bool get()
{
return m_fAutoSkip;
}
}
property wchar_t Character
{
wchar_t get()
{
return m_chChar;
}
void set(wchar_t chValue)
{
m_chChar = chValue;
}
}
property int Display
{
int get()
{
return m_nDisplay;
}
}
property bool Modified
{
bool get()
{
return m_fModified;
}
void set(bool fValue)
{
/* This is only for the field-start */
if (!m_fStartField)
return;
/* Flip bit 7 */
m_chChar = (fValue ? m_chChar | 0x01 : m_chChar & ~0x01);
m_fModified = fValue;
}
}
property int NumericOnly
{
int get()
{
return m_fNumeric;
}
}
property bool Protected
{
bool get()
{
return m_fProtected;
}
}
property bool StartField
{
bool get()
{
return m_fStartField;
}
}
private: /* Private Member Functions */
void UnserializeAttributes();
public: /* Public Member Functions */
C3270Char();
C3270Char(System::Byte chChar);
C3270Char(System::Byte chChar, bool fStartField);
void __Constructor(System::Byte chChar, bool fStartField);
System::Drawing::Brush^ GetPaintBrush();
System::Drawing::Brush^ GetPaintBrush(bool fBaseColor);
virtual System::String^ ToString() override;
System::String^ ToString(bool fMasked);
};
}

1004
CClient3270.cpp Normal file

File diff suppressed because it is too large Load Diff

194
CClient3270.h Normal file
View File

@ -0,0 +1,194 @@
/***********************************************************
WinTN3270
Copyright © 2007 Bob Carroll (bob.carroll@alum.rit.edu)
This software is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation;
either version 2, or (at your option) any later version.
This software is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public
License along with this software; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301 USA
***********************************************************/
#pragma once
#include "CTelnetClient.h"
#include "C3270Char.h"
namespace WinTN3270
{
/***********************************************************
Telnet client for IBM 3270.
***********************************************************/
public ref class CClient3270
{
public: /* Public Delegates */
typedef CTelnetClient::OnCertPolicyError OnCertPolicyError;
private: /* Buffer Address Conversion Table */
static cli::array<int>^ m_mpAddrTbl =
{ 0x40, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
0xC8, 0xC9, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
0x50, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
0xD8, 0xD9, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
0xE8, 0xE9, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
0xF8, 0xF9, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F };
public: // Public Delegates
delegate void OnPaintEvent(int nStartPos, int nEndPos, bool fErase);
private: // Private Member Attributes
bool m_fBaseColor;
bool m_fKeybLocked;
bool m_fSoundAlaram;
bool m_fStartPrinter;
CTelnetClient^ m_mpClient;
cli::array<C3270Char^>^ m_mpCharBuffer;
OnPaintEvent^ m_mpOnPaintCbk;
int m_nActionId;
int m_nBufferPos;
int m_nCursorPos;
int m_nCols;
int m_nLastField;
int m_nLineLength;
int m_nModel;
int m_nRows;
System::Windows::Forms::PictureBox^ m_pnlCanvas;
public: // Public Properties
property bool BaseColorMode
{
bool get()
{
return m_fBaseColor;
}
void set(bool fValue)
{
m_fBaseColor = fValue;
}
}
property cli::array<C3270Char^>^ Buffer
{
cli::array<C3270Char^>^ get() { return m_mpCharBuffer; }
}
property System::Windows::Forms::PictureBox^ Canvas
{
System::Windows::Forms::PictureBox^ get()
{
return m_pnlCanvas;
}
void set(System::Windows::Forms::PictureBox^ pnlCanvas)
{
m_pnlCanvas = pnlCanvas;
}
}
property OnCertPolicyError^ CertificateErrorCallback
{
OnCertPolicyError^ get()
{
return m_mpClient->CertificateErrorCallback;
}
void set(OnCertPolicyError^ mpValue)
{
m_mpClient->CertificateErrorCallback = mpValue;
}
}
property bool Connected
{
bool get() { return m_mpClient->Connected; }
}
property bool Locked
{
bool get() { return m_fKeybLocked; }
}
property int Model
{
int get() { return m_nModel; }
}
property OnPaintEvent^ PaintCallback
{
OnPaintEvent^ get()
{
return m_mpOnPaintCbk;
}
void set(OnPaintEvent^ mpValue)
{
m_mpOnPaintCbk = mpValue;
}
}
property System::Drawing::Size Size
{
System::Drawing::Size get()
{
System::Drawing::Size oSize;
oSize.Height = m_nRows;
oSize.Width = m_nCols;
return oSize;
}
}
private: /* Private Member Functions */
void __Constructor(System::String^ cchIPAddr, int nPort, int nModel);
int ConvertBufferAddress(System::Byte chFirst, System::Byte chSecond);
cli::array<System::Byte>^ CreateActionArray(System::Byte chActionId);
bool DoInputAction(wchar_t chKeyChar);
void EraseAllUnprotected();
void EraseScreen();
int FindStartOfField(int nOffset);
int InterpretOrder(cli::array<System::Byte>^ mpData, int nOffset);
bool IsProtectedField(int nOffset);
void JumpToNextUnprotectedField();
void JumpToPrevUnprotectedField();
cli::array<System::Byte>^ MergeModifiedFields(cli::array<System::Byte>^ mpData);
void MoveCursor(int nStep);
void ParseStream(cli::array<System::Byte>^ mpData, int nLength);
void ReadPartition(int nPartId, int nOpCode);
void ReceiveCallback(cli::array<System::Byte>^ mpData);
void RepaintScreen(int nStartPos, int nEndPos, bool fErase);
void RepeatToAddress(System::Byte chChar, int nStopAddr);
void ResetAllFieldMDTs();
void SendCallback();
bool UnserializeWCC(cli::array<System::Byte>^ mpData, int nOffset);
void WriteBuffer(cli::array<System::Byte>^ mpData, int nOffset, int nLength);
void WriteStructuredField(cli::array<System::Byte>^ mpData, int nOffset);
public: /* Public Member Functions */
CClient3270(System::String^ cchIPAddr, int nPort);
CClient3270(System::String^ cchIPAddr, int nPort, int nModel);
~CClient3270();
void Connect();
void Connect(bool fSecure);
void Disconnect();
void KeyPress(System::Windows::Forms::KeyPressEventArgs^ mpArgs);
void KeyPress(System::Windows::Forms::KeyPressEventArgs^ mpArgs,
System::Windows::Forms::Keys nModifiers);
void MoveCursor(int x, int y);
void MoveCursor(int x, int y, bool fRelative);
void RepaintScreen();
};
}

86
CEbcdicTranslator.cpp Normal file
View File

@ -0,0 +1,86 @@
/***********************************************************
WinTN3270
Copyright © 2007 Bob Carroll (bob.carroll@alum.rit.edu)
This software is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation;
either version 2, or (at your option) any later version.
This software is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public
License along with this software; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301 USA
***********************************************************/
#include "stdafx.h"
#include "CEbcdicTranslator.h"
using namespace WinTN3270;
using namespace System;
/***********************************************************
Translates a byte from EBCDIC to ASCII.
@param mpInput the input byte array
@return an ASCII-encoded character array
***********************************************************/
wchar_t CEbcdicTranslator::CharToASCII(Byte chInput)
{
return (wchar_t)m_mpEbc2AscTbl[(int) chInput];
}
/***********************************************************
Translates a byte from ASCII to EBCDIC.
@param pchInput the input character array
@return an EBCDIC-encoded byte array
***********************************************************/
Byte CEbcdicTranslator::CharToEBCDIC(wchar_t chInput)
{
return (Byte)m_mpAsc2EbcTbl[(int) chInput];
}
/***********************************************************
Translates bytes from EBCDIC to ASCII.
@param mpInput the input byte array
@return an ASCII-encoded character array
***********************************************************/
array<wchar_t>^ CEbcdicTranslator::StringToASCII(array<Byte>^ mpInput)
{
array<wchar_t>^ pchOutput = gcnew array<wchar_t>(mpInput->Length);
/* Convert characters using the EBCDIC-to-ASCII table */
for (int i = 0; i < mpInput->Length; i++)
pchOutput[i] = CEbcdicTranslator::CharToASCII(mpInput[i]);
return pchOutput;
}
/***********************************************************
Translates bytes from ASCII to EBCDIC.
@param pchInput the input character array
@return an EBCDIC-encoded byte array
***********************************************************/
array<Byte>^ CEbcdicTranslator::StringToEBCDIC(array<wchar_t>^ pchInput)
{
array<Byte>^ mpOutput = gcnew array<Byte>(pchInput->Length);
/* Convert characters using the ASCII-to-EBCDIC table */
for (int i = 0; i < pchInput->Length; i++)
mpOutput[i] = CEbcdicTranslator::CharToEBCDIC(pchInput[i]);
return mpOutput;
}

95
CEbcdicTranslator.h Normal file
View File

@ -0,0 +1,95 @@
/***********************************************************
WinTN3270
Copyright © 2007 Bob Carroll (bob.carroll@alum.rit.edu)
This software is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation;
either version 2, or (at your option) any later version.
This software is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public
License along with this software; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301 USA
***********************************************************/
#pragma once
namespace WinTN3270
{
/***********************************************************
Translates strings between ASCII and EBCDIC.
***********************************************************/
public ref class CEbcdicTranslator
{
private: /* ASCII-EBCDIC Conversion Tables */
static cli::array<int>^ m_mpAsc2EbcTbl =
{ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, 0x16, 0x05,
0x25, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
0x3C, 0x3D, 0x32, 0x26, 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D,
0x1E, 0x1F, 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, 0xF0, 0xF1,
0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0x7A, 0x5E,
0x4C, 0x7E, 0x6E, 0x6F, 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5,
0xC6, 0xC7, 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8,
0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D, 0x79, 0x81, 0x82, 0x83,
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94,
0x95, 0x96, 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, 0x00, 0x01,
0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, 0x16, 0x05, 0x25, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D,
0x32, 0x26, 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,
0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 0x4D, 0x5D,
0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, 0xF0, 0xF1, 0xF2, 0xF3,
0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E,
0x6E, 0x6F, 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8,
0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xAD,
0xE0, 0xBD, 0x5F, 0x6D, 0x79, 0x81, 0x82, 0x83, 0x84, 0x85,
0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
0xA9, 0x0, 0x4F, 0xD0, 0xA1, 0x07 };
static cli::array<int>^ m_mpEbc2AscTbl =
{ 0x00, 0x01, 0x02, 0x03, 0x00, 0x09, 0x00, 0x7F, 0x00, 0x00,
0x00, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
0x00, 0x0A, 0x0B, 0x00, 0x18, 0x19, 0x00, 0x00, 0x1C, 0x1D,
0x1E, 0x1F, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0A, 0x17, 0x1B,
0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x07, 0x00, 0x00,
0x16, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
0x14, 0x15, 0x00, 0x1A, 0x20, 0x00, 0xE2, 0xE4, 0xE0, 0xE1,
0xE3, 0xE5, 0xE7, 0xF0, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
0x26, 0xE9, 0xEA, 0xEB, 0xE8, 0xED, 0xEE, 0xEF, 0xEC, 0xDF,
0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E, 0x2D, 0x2F, 0xC2, 0xC4,
0xC0, 0xC1, 0xC3, 0xC5, 0xC7, 0xD1, 0xA6, 0x2C, 0x25, 0x5F,
0x3E, 0x3F, 0xF8, 0xC9, 0xCA, 0xCB, 0xC8, 0xCD, 0xCE, 0xCF,
0xCC, 0x5F, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, 0xD8, 0x61,
0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0xAB, 0xBB,
0xF0, 0x0D, 0xDE, 0xB1, 0xB0, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
0x6F, 0x70, 0x71, 0x72, 0xAA, 0xBA, 0xE6, 0xB8, 0xC6, 0xA4,
0xB5, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
0xA1, 0xBF, 0xD0, 0x5B, 0xFE, 0xAE, 0xAC, 0xA3, 0xA5, 0x95,
0xA9, 0xA7, 0xB6, 0xBC, 0xBD, 0xBE, 0xDD, 0xA8, 0xAF, 0x5D,
0x92, 0xD7, 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x9B, 0xF4, 0xF6, 0xF2, 0xF3, 0xF5, 0x7D, 0x4A,
0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0xB9, 0xFB,
0xFC, 0xF9, 0xFA, 0xFF, 0xFC, 0xF7, 0x53, 0x54, 0x55, 0x56,
0x57, 0x58, 0x59, 0x5A, 0xB2, 0xD4, 0xD6, 0xD2, 0xD3, 0xD5,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0xB3, 0xDB, 0xDC, 0xD9, 0xDA, 0x00 };
public: /* Public Member Functions */
static wchar_t CharToASCII(System::Byte chInput);
static System::Byte CharToEBCDIC(wchar_t chInput);
static cli::array<wchar_t>^ StringToASCII(cli::array<System::Byte>^ mpInput);
static cli::array<System::Byte>^ StringToEBCDIC(cli::array<wchar_t>^ pchInput);
};
}

806
CTelnetClient.cpp Normal file
View File

@ -0,0 +1,806 @@
/***********************************************************
WinTN3270
Copyright © 2007 Bob Carroll (bob.carroll@alum.rit.edu)
This software is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation;
either version 2, or (at your option) any later version.
This software is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public
License along with this software; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301 USA
***********************************************************/
#include "stdafx.h"
#include "CTelnetClient.h"
using namespace WinTN3270;
using namespace System;
using namespace System::Net;
using namespace System::Net::Security;
using namespace System::Net::Sockets;
using namespace System::Security::Authentication;
using namespace System::Security::Cryptography::X509Certificates;
using namespace System::Threading;
using namespace System::Collections;
/* The length of this delegate is absurd */
typedef RemoteCertificateValidationCallback RemoteCertValidateCbk;
/***********************************************************
Creates a new TELNET client.
@param cchIPAddr the IP address of the remote host
@param nPort the remote TCP port
***********************************************************/
CTelnetClient::CTelnetClient(String^ cchIPAddr, int nPort)
{
/* Setup the stream socket */
m_mpSocket = gcnew Socket(
AddressFamily::InterNetwork,
SocketType::Stream,
ProtocolType::Tcp
);
IPHostEntry^ mpRemoteHost = Dns::GetHostEntry(cchIPAddr);
if (mpRemoteHost->AddressList->Length == 0)
throw gcnew Exception("No IP addresses are associated with the host record.");
m_mpRemoteIP = gcnew IPEndPoint(mpRemoteHost->AddressList[0], nPort);
/* Initialize stuff */
m_mpRcvCommandBuffer = gcnew array<Byte>(0);
m_mpRcvDataBuffer = gcnew array<Byte>(0);
m_mpTransmQueue = gcnew array<Byte>(0);
m_mpServerOpts = gcnew Hashtable();
m_mpClientOpts = gcnew Hashtable();
m_cchRemoteHost = cchIPAddr;
m_fGoAhead = true;
m_mpSendEvent = gcnew EventWaitHandle(true, EventResetMode::ManualReset);
/* Set default options */
this->FullDuplex = true;
}
/***********************************************************
Disconnects from the remote host.
***********************************************************/
CTelnetClient::~CTelnetClient()
{
this->Disconnect();
}
/***********************************************************
Callback for validating SSL certificates.
@param mpSender the calling object
@param mpCertificate the cert to validate
@param mpChain the certificate chain
@param ePolicyErrors any policy errors
@return TRUE for valid, FALSE otherwise
***********************************************************/
bool CTelnetClient::CertValidationCallback(Object^ mpSender,
X509Certificate^ mpCertificate, X509Chain^ mpChain,
SslPolicyErrors ePolicyErrors)
{
/* Accept all certs without policy errors */
if (ePolicyErrors == SslPolicyErrors::None)
return true;
/* Get the callback function */
Monitor::Enter(this);
OnCertPolicyError^ mpCertErrorCbk = m_mpCertErrorCbk;
Monitor::Exit(this);
/* If we have no policy error handler, then don't accept */
if (mpCertErrorCbk == nullptr)
return false;
/* Otherwise let the handler decide */
return mpCertErrorCbk->Invoke(
mpCertificate,
mpChain,
ePolicyErrors
);
}
/***********************************************************
Opens a new connection to the remote host.
***********************************************************/
void CTelnetClient::Connect()
{
this->Connect(false);
}
/***********************************************************
Opens a new connection to the remote host.
@param fSecure enable SSL
***********************************************************/
void CTelnetClient::Connect(bool fSecure)
{
/* Make sure we're not already connected */
if (m_mpSocket->Connected)
return;
/* Connect to the remote host */
if (m_mpRemoteIP == nullptr)
throw gcnew Exception("Remote end-point is not set.");
m_mpSocket->Connect(m_mpRemoteIP);
m_mpSocketStream = gcnew NetworkStream(m_mpSocket);
/* If SSL is enabled, then wrap the stream */
if (fSecure) {
m_mpSocketStream = gcnew SslStream(
m_mpSocketStream,
false,
gcnew RemoteCertValidateCbk(this, &CTelnetClient::CertValidationCallback)
);
try {
((SslStream^) m_mpSocketStream)->AuthenticateAsClient(m_cchRemoteHost);
} catch(AuthenticationException^ e) {
m_mpSocket->Disconnect(true);
delete e;
return;
}
}
/* Create the new state struct */
SOCKETRCVSTATE^ mpRcvState = gcnew SOCKETRCVSTATE;
mpRcvState->mpBuffer = gcnew array<Byte>(256);
mpRcvState->mpAscCallback = m_mpReceiveAscCbk;
mpRcvState->mpBinCallback = m_mpReceiveBinCbk;
mpRcvState->mpClient = this;
mpRcvState->mpStream = m_mpSocketStream;
/* Start receving data */
m_mpSocketStream->BeginRead(
mpRcvState->mpBuffer,
0,
mpRcvState->mpBuffer->Length,
gcnew AsyncCallback(&CTelnetClient::ReceiveProc),
mpRcvState
);
}
/***********************************************************
Terminates the active stream connection.
***********************************************************/
void CTelnetClient::Disconnect()
{
if (!m_mpSocket->Connected)
return;
m_mpSocket->Disconnect(true);
}
/***********************************************************
Send all pending transmit data to the remote host.
***********************************************************/
void CTelnetClient::FlushTransmitQueue()
{
/* Copy to our buffer and clear the queue */
Monitor::Enter(this);
array<Byte>^ mpData = gcnew array<Byte>(m_mpTransmQueue->Length);
array<Byte>::Copy(m_mpTransmQueue, mpData, mpData->Length);
m_mpTransmQueue = gcnew array<Byte>(0);
Monitor::Exit(this);
/* We should always have something to send, but... */
if (mpData->Length == 0)
return;
/* Reset the 'go ahead' flag if we're on half-duplex */
if (!this->FullDuplex)
m_fGoAhead = false;
SOCKETSNDSTATE^ mpSndState = gcnew SOCKETSNDSTATE;
mpSndState->mpCallback = m_mpSendCbk;
mpSndState->mpClient = this;
mpSndState->mpStream = m_mpSocketStream;
/* SslStream does not allow concurrent asynchronous writes, so we have to wait
for the last write to finish. */
m_mpSendEvent->WaitOne();
m_mpSendEvent->Reset();
try {
m_mpSocketStream->BeginWrite(
mpData,
0,
mpData->Length,
gcnew AsyncCallback(&CTelnetClient::SendProc),
mpSndState
);
} catch (SocketException^ e) {
throw e;
}
if (mpSndState->mpCallback != nullptr)
mpSndState->mpCallback->Invoke();
}
/***********************************************************
Gets existing option values for the client.
@param nId the option id
@return a byte array containg the value
***********************************************************/
array<Byte>^ CTelnetClient::GetClientOption(int nId)
{
/* Detect if the option isn't set */
if (!m_mpClientOpts->ContainsKey(nId))
return nullptr;
try {
/* First try a direct cast */
return (array<Byte>^)m_mpClientOpts[nId];
} catch (InvalidCastException^ e) {
delete e;
}
try {
/* Maybe it's a boolean? */
return (array<Byte>^)BitConverter::GetBytes( (bool) m_mpClientOpts[nId]);
} catch (InvalidCastException^ e) {
delete e;
}
/* This should never happen */
return gcnew array<Byte>(0);
}
/***********************************************************
Gets existing option values for the server.
@param nId the option id
@return a byte array containg the value
***********************************************************/
array<Byte>^ CTelnetClient::GetServerOption(int nId)
{
/* Detect if the option isn't set */
if (!m_mpServerOpts->ContainsKey(nId))
return nullptr;
try {
/* First try a direct cast */
return (array<Byte>^)m_mpServerOpts[nId];
} catch (InvalidCastException^ e) {
delete e;
}
try {
/* Maybe it's a boolean? */
return (array<Byte>^)BitConverter::GetBytes((bool)m_mpServerOpts[nId]);
} catch (InvalidCastException^ e) {
delete e;
}
/* This should never happen */
return gcnew array<Byte>(0);
}
/***********************************************************
Interprets and handles TELNET commands.
@param mpData the receive data buffer
@return the sanitized array
***********************************************************/
array<Byte>^ CTelnetClient::InterpretCommands(array<Byte>^ mpData)
{
bool fNoDataFlush = (m_mpRcvDataBuffer->Length != 0);
bool fNoCommandFlush = false;
array<Byte>^ mpNewDataBuffer;
array<Byte>^ mpResp;
bool fResult;
/* Merge the incoming data with the buffer */
int nStartIndex = m_mpRcvCommandBuffer->Length;
if (mpData != nullptr) {
array<Byte>::Resize(
m_mpRcvCommandBuffer,
m_mpRcvCommandBuffer->Length + mpData->Length
);
array<Byte>::Copy(mpData, 0, m_mpRcvCommandBuffer, nStartIndex, mpData->Length);
}
if (m_mpRcvCommandBuffer->Length == 0)
return nullptr;
for (int i = 0; i < m_mpRcvCommandBuffer->Length; i++) {
nStartIndex = i;
/* Check for the end-of-record flag */
fNoDataFlush = this->TestServerOption(TELNET_OPTION_END_OF_RECORD);
/* There should never be a single FF character at the end
of the buffer. So if we see one, wait for more data. */
if (m_mpRcvCommandBuffer[i] == TELNET_COMMAND_IAC &&
i == m_mpRcvCommandBuffer->Length - 1)
{
fNoCommandFlush = true;
break;
}
/* If we're in sub-option negotiation and we don't
see an IAC, then capture the option value */
if ((m_mpSubOpt != nullptr && m_mpRcvCommandBuffer[i] != TELNET_COMMAND_IAC) ||
(m_mpSubOpt != nullptr && m_mpRcvCommandBuffer[i] == TELNET_COMMAND_IAC
&& m_mpRcvCommandBuffer[i + 1] == TELNET_COMMAND_IAC))
{
array<Byte>::Resize(
m_mpSubOpt->pchValue,
m_mpSubOpt->pchValue->Length + 1
);
m_mpSubOpt->pchValue[m_mpSubOpt->pchValue->Length - 1] = m_mpRcvCommandBuffer[i];
if (m_mpRcvCommandBuffer[i] == TELNET_COMMAND_IAC)
i++;
continue;
}
/* Two IAC bytes in a row indicate one FF character,
so it's only a command if we see one. */
if (m_mpRcvCommandBuffer[i] != TELNET_COMMAND_IAC ||
(m_mpRcvCommandBuffer[i] == TELNET_COMMAND_IAC &&
m_mpRcvCommandBuffer[i + 1] == TELNET_COMMAND_IAC))
{
array<Byte>::Resize(
m_mpRcvDataBuffer,
m_mpRcvDataBuffer->Length + 1
);
m_mpRcvDataBuffer[m_mpRcvDataBuffer->Length - 1] = m_mpRcvCommandBuffer[i];
if (m_mpRcvCommandBuffer[i] == TELNET_COMMAND_IAC)
i++;
continue;
}
/* If we're at the end of the loop, then buffer the command */
if (i == m_mpRcvCommandBuffer->Length - 1) {
fNoCommandFlush = true;
break;
}
/* Process the given command per RFC0854 */
switch (m_mpRcvCommandBuffer[i + 1]) {
/* End of Record */
case (TELNET_COMMAND_END_OF_RECORD):
/* Flush the data buffer */
mpNewDataBuffer = gcnew array<Byte>(m_mpRcvDataBuffer->Length);
array<Byte>::Copy(
m_mpRcvDataBuffer,
mpNewDataBuffer,
m_mpRcvDataBuffer->Length
);
array<Byte>::Resize(m_mpRcvDataBuffer, 0);
/* Exit and wait for more data */
fNoCommandFlush = true;
nStartIndex = (i + 2);
break;
/* End sub-option negotiation */
case (TELNET_COMMAND_SE):
/* Get the option value */
if (m_mpSubOpt->fValueRequired)
m_mpSubOpt->pchValue = this->GetClientOption(m_mpSubOpt->nOptionId);
/* Send the reply */
mpResp = gcnew array<Byte>(m_mpSubOpt->pchValue->Length + 6);
mpResp[0] = TELNET_COMMAND_IAC;
mpResp[1] = TELNET_COMMAND_SB;
mpResp[2] = m_mpSubOpt->nOptionId;
mpResp[3] = 0x00;
array<Byte>::Copy(
m_mpSubOpt->pchValue,
0,
mpResp,
4,
m_mpSubOpt->pchValue->Length
);
mpResp[m_mpSubOpt->pchValue->Length + 4 + 0] = TELNET_COMMAND_IAC;
mpResp[m_mpSubOpt->pchValue->Length + 4 + 1] = TELNET_COMMAND_SE;
this->Transmit(mpResp);
m_mpSubOpt = nullptr;
i++;
break;
/* No operation */
case (TELNET_COMMAND_NOP):
i += 2;
break;
/* Are you there? */
case (TELNET_COMMAND_ARE_YOU_THERE):
mpResp = gcnew array<Byte>(2);
mpResp[0] = TELNET_COMMAND_IAC;
mpResp[1] = TELNET_COMMAND_NOP;
this->Transmit(mpResp);
i += 2;
break;
/* Go Ahead */
case (TELNET_COMMAND_GA):
m_fGoAhead = true;
this->FlushTransmitQueue();
i += 2;
break;
/* Begin sub-option negotiation */
case (TELNET_COMMAND_SB):
/* Check for all parameters */
if (i + 3 >= m_mpRcvCommandBuffer->Length) {
fNoCommandFlush = true;
break;
}
/* We're in a sub-option now */
m_mpSubOpt = gcnew TNSUBOPTION;
m_mpSubOpt->nOptionId = m_mpRcvCommandBuffer[i + 2];
m_mpSubOpt->pchValue = gcnew array<Byte>(0);
m_mpSubOpt->fValueRequired = BitConverter::ToBoolean( m_mpRcvCommandBuffer, i + 3);
i += 3;
break;
/* Client is offering an option */
case (TELNET_COMMAND_WILL):
/* Check for all parameters */
if (i + 2 >= m_mpRcvCommandBuffer->Length) {
fNoCommandFlush = true;
break;
}
/* Get the client option */
fResult = (this->GetClientOption(m_mpRcvCommandBuffer[i + 2]) != nullptr);
/* Send the reply */
mpResp = gcnew array<Byte>(3);
mpResp[0] = TELNET_COMMAND_IAC;
mpResp[1] = (fResult ? TELNET_COMMAND_DO : TELNET_COMMAND_DONT);
mpResp[2] = m_mpRcvCommandBuffer[i + 2];
this->Transmit(mpResp);
i += 2;
break;
/* Client won't do an option */
case (TELNET_COMMAND_WONT):
/* Check for all parameters */
if (i + 2 >= m_mpRcvCommandBuffer->Length) {
fNoCommandFlush = true;
break;
}
/* Attempt to unset the option */
fResult = this->SetServerOption(m_mpRcvCommandBuffer[i + 2], nullptr);
// Send the reply
mpResp = gcnew array<Byte>(3);
mpResp[0] = TELNET_COMMAND_IAC;
mpResp[1] = (!fResult ? TELNET_COMMAND_DO : TELNET_COMMAND_DONT);
mpResp[2] = m_mpRcvCommandBuffer[i + 2];
this->Transmit(mpResp);
i += 2;
break;
/* Client wants an option */
case (TELNET_COMMAND_DO):
/* Check for all parameters */
if (i + 2 >= m_mpRcvCommandBuffer->Length) {
fNoCommandFlush = true;
break;
}
/* Attempt to set the option */
fResult = this->SetServerOption(m_mpRcvCommandBuffer[i + 2], true);
// Send the reply
mpResp = gcnew array<Byte>(3);
mpResp[0] = TELNET_COMMAND_IAC;
mpResp[1] = (fResult ? TELNET_COMMAND_WILL : TELNET_COMMAND_WONT);
mpResp[2] = m_mpRcvCommandBuffer[i + 2];
this->Transmit(mpResp);
i += 2;
break;
/* Client doesn't want an option */
case (TELNET_COMMAND_DONT):
/* Check for all parameters */
if (i + 2 >= m_mpRcvCommandBuffer->Length) {
fNoCommandFlush = true;
break;
}
/* Attempt to unset the option */
fResult = this->SetServerOption(m_mpRcvCommandBuffer[i + 2], nullptr);
// Send the reply
mpResp = gcnew array<Byte>(3);
mpResp[0] = TELNET_COMMAND_IAC;
mpResp[1] = (!fResult ? TELNET_COMMAND_WILL : TELNET_COMMAND_WONT);
mpResp[2] = m_mpRcvCommandBuffer[i + 2];
this->Transmit(mpResp);
i += 2;
break;
/* Unsupported command */
default:
i++;
}
if (fNoCommandFlush)
break;
}
if (fNoCommandFlush) {
/* Shift the remaining data to the start of the buffer
because we're waiting for the complete request to arrive */
array<Byte>::Copy(
m_mpRcvCommandBuffer,
nStartIndex,
m_mpRcvCommandBuffer,
0,
m_mpRcvCommandBuffer->Length - nStartIndex
);
array<Byte>::Resize(
m_mpRcvCommandBuffer,
m_mpRcvCommandBuffer->Length - nStartIndex
);
} else {
/* We're at the end, empty the buffer */
array<Byte>::Resize(m_mpRcvCommandBuffer, 0);
}
if (!fNoDataFlush && m_mpRcvDataBuffer->Length > 0) {
/* Move data from the receive buffer */
mpNewDataBuffer = gcnew array<Byte>(m_mpRcvDataBuffer->Length);
array<Byte>::Copy(
m_mpRcvDataBuffer,
mpNewDataBuffer,
m_mpRcvDataBuffer->Length
);
array<Byte>::Resize(m_mpRcvDataBuffer, 0);
}
return mpNewDataBuffer;
}
/***********************************************************
Callback function for asynchronous receiving.
***********************************************************/
void CTelnetClient::ReceiveProc(IAsyncResult^ mpResult)
{
/* Finish the receive operation */
SOCKETRCVSTATE^ mpRcvState = safe_cast<SOCKETRCVSTATE^>(mpResult->AsyncState);
int nBytesRead = mpRcvState->mpStream->EndRead(mpResult);
/* If we got some data back... */
if (nBytesRead > 0) {
/* Trim the fat off the new buffer */
array<Byte>::Resize(mpRcvState->mpBuffer, nBytesRead);
while (true) {
/* Process TELNET commands */
mpRcvState->mpBuffer = mpRcvState->mpClient->InterpretCommands(mpRcvState->mpBuffer);
if (mpRcvState->mpBuffer == nullptr)
break;
if (mpRcvState->mpBuffer->Length > 0 && mpRcvState->mpClient->BinaryTransmission) {
if (mpRcvState->mpBinCallback != nullptr)
mpRcvState->mpBinCallback->Invoke(mpRcvState->mpBuffer);
} else if (mpRcvState->mpBuffer->Length > 0) {
/* Convert it to a string */
array<wchar_t>^ pchData = gcnew array<wchar_t>(mpRcvState->mpBuffer->Length);
array<wchar_t>::Copy(mpRcvState->mpBuffer, pchData, mpRcvState->mpBuffer->Length);
String^ cchDataStr = gcnew String(pchData);
if (mpRcvState->mpAscCallback != nullptr)
mpRcvState->mpAscCallback->Invoke(cchDataStr);
}
/* Empty the buffer */
mpRcvState->mpBuffer = gcnew array<Byte>(0);
}
}
SOCKETRCVSTATE^ mpNewRcvState = gcnew SOCKETRCVSTATE;
mpNewRcvState->mpBuffer = gcnew array<Byte>(256);
mpNewRcvState->mpAscCallback = mpRcvState->mpAscCallback;
mpNewRcvState->mpBinCallback = mpRcvState->mpBinCallback;
mpNewRcvState->mpClient = mpRcvState->mpClient;
mpNewRcvState->mpStream = mpRcvState->mpStream;
try {
/* Start receving data again */
mpRcvState->mpStream->BeginRead(
mpNewRcvState->mpBuffer,
0,
mpNewRcvState->mpBuffer->Length,
gcnew AsyncCallback(&CTelnetClient::ReceiveProc),
mpNewRcvState
);
} catch (SocketException^ e) {
delete e;
}
}
/***********************************************************
Sends string data to the remote host.
@param cchData the string data to send
***********************************************************/
void CTelnetClient::Send(String^ cchData)
{
Text::Encoding^ mpEncoding = Text::ASCIIEncoding::Default;
array<Byte>^ mpBytes = (array<Byte>^)mpEncoding->GetBytes(cchData);
this->Send(mpBytes);
}
/***********************************************************
Sends byte data to the remote host.
@param mpData the byte data to send
***********************************************************/
void CTelnetClient::Send(array<Byte>^ mpData)
{
array<Byte>^ mpNewData = gcnew array<Byte>(0);
int n = 0;
for (int i = 0; i < mpData->Length; i++) {
array<Byte>::Resize(
mpNewData,
mpNewData->Length + (mpData[i] == 0xFF ? 2 : 1)
);
mpNewData[n] = mpData[i];
n++;
/* Escape FF */
if (mpData[i] == 0xFF) {
mpNewData[n] = mpData[i];
n++;
}
}
/* Detect end-of-record option and append IAC EOR if needed */
if (m_mpServerOpts->ContainsKey(TELNET_OPTION_END_OF_RECORD)) {
array<Byte>::Resize(mpNewData, mpNewData->Length + 2);
mpNewData[mpNewData->Length - 2] = TELNET_COMMAND_IAC;
mpNewData[mpNewData->Length - 1] = TELNET_COMMAND_END_OF_RECORD;
}
this->Transmit(mpNewData);
}
/***********************************************************
Callback function for asynchronous sending.
***********************************************************/
void CTelnetClient::SendProc(System::IAsyncResult^ mpResult)
{
SOCKETSNDSTATE^ mpSndState = safe_cast<SOCKETSNDSTATE^>(mpResult->AsyncState);
mpSndState->mpStream->EndWrite(mpResult);
mpSndState->mpClient->m_mpSendEvent->Set();
}
/***********************************************************
Enables a terminal option for the server.
@param nId the option id
@param fValue the option value (nullptr to unset)
@return TRUE if the option is support, FALSE otherwise
***********************************************************/
bool CTelnetClient::SetServerOption(int nId, bool fValue)
{
return this->SetServerOption(nId, BitConverter::GetBytes(fValue));
}
/***********************************************************
Enables a terminal option for the server.
@param nId the option id
@param mpValue the option value (nullptr to unset)
@return TRUE if the option is support, FALSE otherwise
***********************************************************/
bool CTelnetClient::SetServerOption(int nId, array<Byte>^ mpValue)
{
/* Validate the input, and handle special cases */
if (mpValue == nullptr && m_mpServerOpts->ContainsKey(nId))
m_mpServerOpts->Remove(nId);
else if (mpValue == nullptr && !m_mpServerOpts->ContainsKey(nId))
return false;
else if (mpValue != nullptr && m_mpServerOpts->ContainsKey(nId))
return true;
/* Select supported options */
switch (nId) {
/* Binary Transmission */
case (TELNET_OPTION_BINARY):
return m_mpClientOpts->ContainsKey(safe_cast<int^>(TELNET_OPTION_TERM_TYPE));
/* Suppress Go Ahead */
case (TELNET_OPTION_SUPPRESS_GA):
return m_mpClientOpts->ContainsKey(safe_cast<int^>(TELNET_OPTION_SUPPRESS_GA));
/* Terminal Type */
case (TELNET_OPTION_TERM_TYPE):
return m_mpClientOpts->ContainsKey(TELNET_OPTION_TERM_TYPE);
/* End of Record */
case (TELNET_OPTION_END_OF_RECORD):
m_mpServerOpts->Add(TELNET_OPTION_END_OF_RECORD, true);
return true;
}
/* Everything else is unsupported */
return false;
}
/***********************************************************
Tests for both the existance of, and the value of a
server option.
@param nId the option id
@return a boolean representation of the value
***********************************************************/
bool CTelnetClient::TestServerOption(int nId)
{
/* Detect if the option isn't set */
if (!m_mpServerOpts->ContainsKey(nId))
return false;
try {
return (bool)m_mpServerOpts[nId];
} catch (InvalidCastException^ e) {
delete e;
}
return false;
}
/***********************************************************
Sends byte data to the remote host.
@param mpData the byte data to send
***********************************************************/
void CTelnetClient::Transmit(array<Byte>^ mpData)
{
/* Copy our buffer to the queue */
Monitor::Enter(this);
int nQueueIndex = m_mpTransmQueue->Length;
array<Byte>::Resize(
m_mpTransmQueue,
m_mpTransmQueue->Length + mpData->Length
);
array<Byte>::Copy(
mpData,
0,
m_mpTransmQueue,
nQueueIndex,
mpData->Length
);
Monitor::Exit(this);
if (this->FullDuplex || (!this->FullDuplex && m_fGoAhead))
this->FlushTransmitQueue();
}

241
CTelnetClient.h Normal file
View File

@ -0,0 +1,241 @@
/***********************************************************
WinTN3270
Copyright © 2007 Bob Carroll (bob.carroll@alum.rit.edu)
This software is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation;
either version 2, or (at your option) any later version.
This software is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public
License along with this software; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301 USA
***********************************************************/
#pragma once
#include "TelnetProtocol.h"
namespace WinTN3270
{
/***********************************************************
Client for communicating with a remote TELNET server.
***********************************************************/
public ref class CTelnetClient
{
public: /* Public Delegates */
delegate bool OnCertPolicyError(
System::Security::Cryptography::X509Certificates::X509Certificate^ mpCertificate,
System::Security::Cryptography::X509Certificates::X509Chain^ mpChain,
System::Net::Security::SslPolicyErrors ePolicyErrors);
delegate void OnReceiveASCII(System::String^ cchData);
delegate void OnReceiveBinary(cli::array<System::Byte>^ mpData);
delegate void OnSend();
private: /* Private Member Attributes */
System::String^ m_cchRemoteHost;
bool m_fGoAhead;
OnCertPolicyError^ m_mpCertErrorCbk;
System::Collections::Hashtable^ m_mpClientOpts;
System::Threading::EventWaitHandle^ m_mpSendEvent;
cli::array<System::Byte>^ m_mpRcvCommandBuffer;
cli::array<System::Byte>^ m_mpRcvDataBuffer;
OnReceiveASCII^ m_mpReceiveAscCbk;
OnReceiveBinary^ m_mpReceiveBinCbk;
System::Net::IPEndPoint^ m_mpRemoteIP;
OnSend^ m_mpSendCbk;
System::Collections::Hashtable^ m_mpServerOpts;
System::Net::Sockets::Socket^ m_mpSocket;
System::IO::Stream^ m_mpSocketStream;
TNSUBOPTION^ m_mpSubOpt;
cli::array<System::Byte>^ m_mpTransmQueue;
public: /* Public Properties */
property bool BinaryTransmission
{
bool get()
{
return m_mpClientOpts->ContainsKey(safe_cast<int^>(TELNET_OPTION_BINARY));
}
void set(bool fValue)
{
if (!fValue &&
m_mpClientOpts->ContainsKey(safe_cast<int^>(TELNET_OPTION_BINARY)))
{
m_mpClientOpts->Remove(safe_cast<int^>(TELNET_OPTION_BINARY));
}
m_mpClientOpts[safe_cast<int^>(TELNET_OPTION_BINARY)] = true;
}
}
property OnCertPolicyError^ CertificateErrorCallback
{
OnCertPolicyError^ get()
{
System::Threading::Monitor::Enter(this);
OnCertPolicyError^ mpCertErrorCbk = m_mpCertErrorCbk;
System::Threading::Monitor::Exit(this);
return mpCertErrorCbk;
}
void set(OnCertPolicyError^ mpValue)
{
System::Threading::Monitor::Enter(this);
m_mpCertErrorCbk = mpValue;
System::Threading::Monitor::Exit(this);
}
}
property bool Connected
{
bool get() { return m_mpSocket->Connected; }
}
property bool EndOfRecord
{
bool get()
{
return m_mpClientOpts->ContainsKey(TELNET_OPTION_END_OF_RECORD);
}
void set(bool fValue)
{
if (!fValue &&
m_mpClientOpts->ContainsKey(TELNET_OPTION_END_OF_RECORD))
{
m_mpClientOpts->Remove(TELNET_OPTION_END_OF_RECORD);
return;
}
m_mpClientOpts[TELNET_OPTION_END_OF_RECORD] = true;
}
}
property bool FullDuplex
{
bool get()
{
return m_mpClientOpts->ContainsKey(TELNET_OPTION_SUPPRESS_GA);
}
void set(bool fValue)
{
if (!fValue &&
m_mpClientOpts->ContainsKey(TELNET_OPTION_SUPPRESS_GA))
{
m_mpClientOpts->Remove(TELNET_OPTION_SUPPRESS_GA);
return;
}
m_mpClientOpts[TELNET_OPTION_SUPPRESS_GA] = true;
}
}
property OnReceiveASCII^ ReceiveCallbackASCII
{
OnReceiveASCII^ get() { return m_mpReceiveAscCbk; }
void set(OnReceiveASCII^ mpValue)
{
m_mpReceiveAscCbk = mpValue;
}
}
property OnReceiveBinary^ ReceiveCallbackBinary
{
OnReceiveBinary^ get() { return m_mpReceiveBinCbk; }
void set(OnReceiveBinary^ mpValue)
{
m_mpReceiveBinCbk = mpValue;
}
}
property OnSend^ SendCallback
{
OnSend^ get() { return m_mpSendCbk; }
void set(OnSend^ mpValue)
{
m_mpSendCbk = mpValue;
}
}
property cli::array<System::Byte>^ TerminalType
{
cli::array<System::Byte>^ get()
{
if (!m_mpClientOpts->ContainsKey(TELNET_OPTION_TERM_TYPE))
return nullptr;
return (cli::array<System::Byte>^)m_mpClientOpts[TELNET_OPTION_TERM_TYPE];
}
void set(cli::array<System::Byte>^ mpValue)
{
if (mpValue == nullptr &&
m_mpClientOpts->ContainsKey(TELNET_OPTION_TERM_TYPE))
{
m_mpClientOpts->Remove(TELNET_OPTION_TERM_TYPE);
return;
}
m_mpClientOpts[TELNET_OPTION_TERM_TYPE] = mpValue;
}
}
private: /* Private Member Functions */
bool CertValidationCallback( System::Object^ mpSender,
System::Security::Cryptography::X509Certificates::X509Certificate^ mpCertificate,
System::Security::Cryptography::X509Certificates::X509Chain^ mpChain,
System::Net::Security::SslPolicyErrors ePolicyErrors);
void FlushTransmitQueue();
cli::array<System::Byte>^ GetClientOption(int nId);
cli::array<System::Byte>^ InterpretCommands(cli::array<System::Byte>^ mpData);
static void ReceiveProc(System::IAsyncResult^ mpResult);
static void SendProc(System::IAsyncResult^ mpResult);
bool SetServerOption(int nId, bool fValue);
bool SetServerOption(int nId, cli::array<System::Byte>^ mpValue);
void Transmit(cli::array<System::Byte>^ mpData);
public: /* Public Member Functions */
CTelnetClient(System::String^ cchIPAddr, int nPort);
~CTelnetClient();
void Connect();
void Connect(bool fSecure);
void Disconnect();
cli::array<System::Byte>^ GetServerOption(int nId);
void Send(System::String^ cchData);
void Send(cli::array<System::Byte>^ mpData);
bool TestServerOption(int nId);
};
/* Socket Receive State */
ref struct SOCKETRCVSTATE
{
cli::array<System::Byte>^ mpBuffer;
CTelnetClient::OnReceiveASCII^ mpAscCallback;
CTelnetClient::OnReceiveBinary^ mpBinCallback;
CTelnetClient^ mpClient;
System::IO::Stream^ mpStream;
};
/* Socket Send State */
ref struct SOCKETSNDSTATE
{
CTelnetClient::OnSend^ mpCallback;
CTelnetClient^ mpClient;
System::IO::Stream^ mpStream;
};
}

119
CWndMain.cpp Normal file
View File

@ -0,0 +1,119 @@
/***********************************************************
WinTN3270
Copyright © 2007 Bob Carroll (bob.carroll@alum.rit.edu)
This software is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation;
either version 2, or (at your option) any later version.
This software is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public
License along with this software; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301 USA
***********************************************************/
#include "stdafx.h"
#include "CWndMain.h"
using namespace WinTN3270;
using namespace System;
using namespace System::Net::Security;
using namespace System::Security::Cryptography::X509Certificates;
using namespace System::Windows;
/***********************************************************
Handles the form load event.
***********************************************************/
Void CWndMain::CWndMain_Load(Object^ sender, EventArgs^ e)
{
/* Prep the canvas */
pbxCanvas->BackColor = Color::Black;
m_mpClient = gcnew CClient3270("mvs.example.com", 992, 2);
m_mpClient->Canvas = pbxCanvas;
m_mpClient->CertificateErrorCallback = gcnew CClient3270::OnCertPolicyError(
this,
&CWndMain::m_mpClient_CertPolicyError
);
m_mpClient->Connect(true);
}
/***********************************************************
Handles the key down event for the canvas.
***********************************************************/
System::Void CWndMain::CWndMain_KeyDown(System::Object^ sender, KeyEventArgs^ e)
{
switch (e->KeyCode) {
case ConsoleKey::LeftArrow:
m_mpClient->MoveCursor(-1, 0, true);
break;
case ConsoleKey::RightArrow:
m_mpClient->MoveCursor(1, 0, true);
break;
case ConsoleKey::UpArrow:
m_mpClient->MoveCursor(0, -1, true);
break;
case ConsoleKey::DownArrow:
m_mpClient->MoveCursor(0, 1, true);
break;
case ConsoleKey::F12:
m_mpClient->KeyPress(gcnew KeyPressEventArgs((wchar_t) ConsoleKey::F12));
break;
}
}
/***********************************************************
Handles the key press event for the canvas.
***********************************************************/
System::Void CWndMain::CWndMain_KeyPress(System::Object^ sender, KeyPressEventArgs^ e)
{
m_mpClient->KeyPress(e, this->ModifierKeys);
}
/***********************************************************
Handles the form paint event.
***********************************************************/
void CWndMain::OnPaint(PaintEventArgs^ e)
{
/* Re-draw the terminal display */
m_mpClient->RepaintScreen();
}
/***********************************************************
Callback for handling SSL policy errors.
@param mpCertificate the cert to validate
@param mpChain the certificate chain
@param ePolicyErrors any policy errors
@return TRUE for valid, FALSE otherwise
***********************************************************/
bool CWndMain::m_mpClient_CertPolicyError(X509Certificate^ mpCertificate,
X509Chain^ mpChain, SslPolicyErrors ePolicyErrors)
{
String^ mpErrors = "";
if ((ePolicyErrors & SslPolicyErrors::RemoteCertificateChainErrors) == SslPolicyErrors::RemoteCertificateChainErrors)
mpErrors += "\n\n* The security certificate is not from a trusted authority.";
if ((ePolicyErrors & SslPolicyErrors::RemoteCertificateNameMismatch) == SslPolicyErrors::RemoteCertificateNameMismatch)
mpErrors += "\n\n* The name on the security certificate is invalid or does not match the name of the remote host.";
if ((ePolicyErrors & SslPolicyErrors::RemoteCertificateNotAvailable) == SslPolicyErrors::RemoteCertificateNotAvailable)
mpErrors += "\n\n* The security certificate is not available.";
return MessageBox::Show("There is a problem with remote host's security certificate!"
+ mpErrors + "\n\nDo you want to proceed?", "Security Warning",
MessageBoxButtons::YesNo, MessageBoxIcon::Exclamation,
MessageBoxDefaultButton::Button2) == Forms::DialogResult::Yes;
}

152
CWndMain.h Normal file
View File

@ -0,0 +1,152 @@
#pragma once
#include "CClient3270.h"
namespace WinTN3270 {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Summary for Form1
///
/// WARNING: If you change the name of this class, you will need to change the
/// 'Resource File Name' property for the managed resource compiler tool
/// associated with all .resx files this class depends on. Otherwise,
/// the designers will not be able to interact properly with localized
/// resources associated with this form.
/// </summary>
public ref class CWndMain : public System::Windows::Forms::Form
{
public:
CWndMain(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
protected:
/// <summary>
/// Clean up any resources being used.
/// </summary>
~CWndMain()
{
if (components)
{
delete components;
}
}
private: System::Windows::Forms::MenuStrip^ mnuMain;
private: System::Windows::Forms::StatusStrip^ sbrMain;
protected:
protected:
private: System::Windows::Forms::ToolStrip^ tlbMain;
private: System::Windows::Forms::PictureBox^ pbxCanvas;
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->mnuMain = (gcnew System::Windows::Forms::MenuStrip());
this->sbrMain = (gcnew System::Windows::Forms::StatusStrip());
this->tlbMain = (gcnew System::Windows::Forms::ToolStrip());
this->pbxCanvas = (gcnew System::Windows::Forms::PictureBox());
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pbxCanvas))->BeginInit();
this->SuspendLayout();
//
// mnuMain
//
this->mnuMain->Location = System::Drawing::Point(0, 0);
this->mnuMain->Name = L"mnuMain";
this->mnuMain->Size = System::Drawing::Size(817, 24);
this->mnuMain->TabIndex = 0;
this->mnuMain->Text = L"menuStrip1";
//
// sbrMain
//
this->sbrMain->Location = System::Drawing::Point(0, 539);
this->sbrMain->Name = L"sbrMain";
this->sbrMain->Size = System::Drawing::Size(817, 22);
this->sbrMain->TabIndex = 1;
this->sbrMain->Text = L"statusStrip1";
//
// tlbMain
//
this->tlbMain->Location = System::Drawing::Point(0, 24);
this->tlbMain->Name = L"tlbMain";
this->tlbMain->Size = System::Drawing::Size(817, 25);
this->tlbMain->TabIndex = 2;
this->tlbMain->Text = L"toolStrip1";
//
// pbxCanvas
//
this->pbxCanvas->Anchor = static_cast<System::Windows::Forms::AnchorStyles>((((System::Windows::Forms::AnchorStyles::Top | System::Windows::Forms::AnchorStyles::Bottom)
| System::Windows::Forms::AnchorStyles::Left)
| System::Windows::Forms::AnchorStyles::Right));
this->pbxCanvas->Location = System::Drawing::Point(0, 51);
this->pbxCanvas->Name = L"pbxCanvas";
this->pbxCanvas->Size = System::Drawing::Size(817, 485);
this->pbxCanvas->TabIndex = 3;
this->pbxCanvas->TabStop = false;
//
// CWndMain
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(817, 561);
this->Controls->Add(this->pbxCanvas);
this->Controls->Add(this->tlbMain);
this->Controls->Add(this->sbrMain);
this->Controls->Add(this->mnuMain);
this->MainMenuStrip = this->mnuMain;
this->Name = L"CWndMain";
this->Text = L"CWndMain";
this->KeyPress += gcnew System::Windows::Forms::KeyPressEventHandler(this, &CWndMain::CWndMain_KeyPress);
this->KeyDown += gcnew System::Windows::Forms::KeyEventHandler(this, &CWndMain::CWndMain_KeyDown);
this->Load += gcnew System::EventHandler(this, &CWndMain::CWndMain_Load);
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pbxCanvas))->EndInit();
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
private: /* Private Member Attributes */
CClient3270^ m_mpClient;
private: /* Private Member Functions */
System::Void CWndMain_Load(System::Object^ sender, System::EventArgs^ e);
System::Void CWndMain_KeyDown(System::Object^ sender,
System::Windows::Forms::KeyEventArgs^ e);
System::Void CWndMain_KeyPress(System::Object^ sender,
System::Windows::Forms::KeyPressEventArgs^ e);
bool m_mpClient_CertPolicyError(
System::Security::Cryptography::X509Certificates::X509Certificate^ mpCertificate,
System::Security::Cryptography::X509Certificates::X509Chain^ mpChain,
System::Net::Security::SslPolicyErrors ePolicyErrors);
protected: /* Overrides */
virtual void OnPaint(PaintEventArgs^ e) override;
};
}

129
CWndMain.resx Normal file
View File

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="mnuMain.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="sbrMain.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>126, 17</value>
</metadata>
<metadata name="tlbMain.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>236, 17</value>
</metadata>
</root>

120
IBM3270.h Normal file
View File

@ -0,0 +1,120 @@
/***********************************************************
WinTN3270
Copyright © 2007 Bob Carroll (bob.carroll@alum.rit.edu)
This software is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation;
either version 2, or (at your option) any later version.
This software is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public
License along with this software; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301 USA
***********************************************************/
/***********************************************************
Constants for the IBM 3270 data stream protocol.
***********************************************************/
#pragma once
/* Commands (ASCII) */
#define IBM3270DS_CMD_EAU 0x0F /* Erase All Unprotected */
#define IBM3270DS_CMD_EW 0x05 /* Erase Write */
#define IBM3270DS_CMD_EWA 0x0D /* Erase Write Alternate */
#define IBM3270DS_CMD_NOP 0x03 /* No Operation */
#define IBM3270DS_CMD_RB 0x02 /* Read Buffer */
#define IBM3270DS_CMD_RM 0x06 /* Read Modified */
#define IBM3270DS_CMD_RMA 0x0E /* Read Modified All */
#define IBM3270DS_CMD_W 0x01 /* Write */
#define IBM3270DS_CMD_WSF 0x11 /* Write Structured Field */
/* Commands (EBCDIC) */
#define IBM3270DS_CMD_EAU_EBCDIC 0x6F /* Erase All Unprotected */
#define IBM3270DS_CMD_EW_EBCDIC 0xF5 /* Erase Write */
#define IBM3270DS_CMD_EWA_EBCDIC 0x7E /* Erase Write Alternate */
#define IBM3270DS_CMD_RB_EBCDIC 0xF2 /* Read Buffer */
#define IBM3270DS_CMD_RM_EBCDIC 0xF6 /* Read Modified */
#define IBM3270DS_CMD_RMA_EBCDIC 0x6E /* Read Modified All */
#define IBM3270DS_CMD_W_EBCDIC 0xF1 /* Write */
#define IBM3270DS_CMD_WSF_EBCDIC 0xF3 /* Write Structured Field */
/* Orders */
#define IBM3270DS_ORDER_EUA 0x12 /* Erase Unprotected to Address */
#define IBM3270DS_ORDER_GE 0x08 /* Graphic Escape */
#define IBM3270DS_ORDER_IC 0x13 /* Insert Cursor */
#define IBM3270DS_ORDER_MF 0x2C /* Modify Field */
#define IBM3270DS_ORDER_PT 0x05 /* Program Tab */
#define IBM3270DS_ORDER_RA 0x3C /* Repeat to Address */
#define IBM3270DS_ORDER_SA 0x28 /* Set Attribute */
#define IBM3270DS_ORDER_SBA 0x11 /* Set Buffer Address */
#define IBM3270DS_ORDER_SF 0x1D /* Start Field */
#define IBM3270DS_ORDER_SFE 0x29 /* Start Field Extended */
/* Action IDs */
#define IBM3270DS_AID_CLEAR 0x6D
#define IBM3270DS_AID_ENTER 0x7D
#define IBM3270DS_AID_NONE 0x60
#define IBM3270DS_AID_PA1 0x6C
#define IBM3270DS_AID_PA2 0x6E
#define IBM3270DS_AID_PA3 0x6B
#define IBM3270DS_AID_PF1 0xF1
#define IBM3270DS_AID_PF2 0xF2
#define IBM3270DS_AID_PF3 0xF3
#define IBM3270DS_AID_PF4 0xF4
#define IBM3270DS_AID_PF5 0xF5
#define IBM3270DS_AID_PF6 0xF6
#define IBM3270DS_AID_PF7 0xF7
#define IBM3270DS_AID_PF8 0xF8
#define IBM3270DS_AID_PF9 0xF9
#define IBM3270DS_AID_PF10 0x7A
#define IBM3270DS_AID_PF11 0x7B
#define IBM3270DS_AID_PF12 0x7C
#define IBM3270DS_AID_PF13 0xC1
#define IBM3270DS_AID_PF14 0xC2
#define IBM3270DS_AID_PF15 0xC3
#define IBM3270DS_AID_PF16 0xC4
#define IBM3270DS_AID_PF17 0xC5
#define IBM3270DS_AID_PF18 0xC6
#define IBM3270DS_AID_PF19 0xC7
#define IBM3270DS_AID_PF20 0xC8
#define IBM3270DS_AID_PF21 0xC9
#define IBM3270DS_AID_PF22 0x4A
#define IBM3270DS_AID_PF23 0x4B
#define IBM3270DS_AID_PF24 0x4C
#define IBM3270DS_AID_SF 0x88
/* Structured Field Operations */
#define IBM3270DS_SF_ERASE_RESET 0x03 /* Erase/Reset */
#define IBM3270DS_SF_OUTBOUND_DS 0x40 /* Outbound 3270 DS */
#define IBM3270DS_SF_QUERY_REPLY 0x81 /* Query Reply */
#define IBM3270DS_SF_READ_PART 0x01 /* Read Partition */
#define IBM3270DS_SF_RESET_PART 0x00 /* Reset Partition */
#define IBM3270DS_SF_SET_REPLY_MODE 0x09 /* Set Reply Mode */
#define IBM3270DS_SF_TRANSFER_DATA 0xd0 /* File Transfer Open Request */
/* SF Erase/Write Operations */
#define IBM3270DS_SF_ER_DEFAULT 0x00 /* Default */
#define IBM3270DS_SF_ER_ALT 0x80 /* Alternate */
/* SF Read Partition Operations */
#define IBM3270DS_SF_RP_QUERY 0x02 /* Query */
#define IBM3270DS_SF_RP_QLIST 0x03 /* Query List */
#define IBM3270DS_SF_RP_RB 0xF2 /* Read Buffer */
#define IBM3270DS_SF_RP_RM 0xF6 /* Read Modified */
#define IBM3270DS_SF_RP_RMA 0x6E /* Read Modified All */
/* SF Set Reply Mode Operations */
#define IBM3270DS_SF_SRM_FIELD 0x00 /* Field */
#define IBM3270DS_SF_SRM_XFIELD 0x01 /* Extended Field */
#define IBM3270DS_SF_SRM_CHAR 0x02 /* Character */
/* SF Query Reply Codes */
#define IBM3270DS_SF_QR_NULL 0xFF /* Null */

61
TelnetProtocol.h Normal file
View File

@ -0,0 +1,61 @@
/***********************************************************
WinTN3270
Copyright © 2007 Bob Carroll (bob.carroll@alum.rit.edu)
This software is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation;
either version 2, or (at your option) any later version.
This software is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public
License along with this software; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301 USA
***********************************************************/
/***********************************************************
Constants and data structures for TELNET.
***********************************************************/
#pragma once
/* Commands */
#define TELNET_COMMAND_END_OF_RECORD 0xEF
#define TELNET_COMMAND_SE 0xF0
#define TELNET_COMMAND_NOP 0xF1
#define TELNET_COMMAND_DATA_MARK 0xF2
#define TELNET_COMMAND_BREAK 0xF3
#define TELNET_COMMAND_INTERRUPT 0xF4
#define TELNET_COMMAND_ABORT 0xF5
#define TELNET_COMMAND_ARE_YOU_THERE 0xF6
#define TELNET_COMMAND_ERASE_CHAR 0xF7
#define TELNET_COMMAND_ERASE_LINE 0xF8
#define TELNET_COMMAND_GA 0xF9
#define TELNET_COMMAND_SB 0xFA
#define TELNET_COMMAND_WILL 0xFB
#define TELNET_COMMAND_WONT 0xFC
#define TELNET_COMMAND_DO 0xFD
#define TELNET_COMMAND_DONT 0xFE
#define TELNET_COMMAND_IAC 0xFF
/* Options */
#define TELNET_OPTION_BINARY 0x00
#define TELNET_OPTION_ECHO 0x01
#define TELNET_OPTION_SUPPRESS_GA 0x03
#define TELNET_OPTION_TERM_TYPE 0x18
#define TELNET_OPTION_END_OF_RECORD 0x19
#define TELNET_OPTION_TN3270E 0x28
/* Sub-Option Structure */
ref struct TNSUBOPTION
{
cli::array<System::Byte>^ pchValue;
bool fValueRequired;
int nOptionId;
};

43
WinTN3270.cpp Normal file
View File

@ -0,0 +1,43 @@
/***********************************************************
WinTN3270
Copyright © 2007 Bob Carroll (bob.carroll@alum.rit.edu)
This software is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation;
either version 2, or (at your option) any later version.
This software is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public
License along with this software; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301 USA
***********************************************************/
#include "stdafx.h"
#include "CWndMain.h"
using namespace WinTN3270;
/***********************************************************
Application entry-point function
@param args the command line arguments
@return the program return code
***********************************************************/
[STAThreadAttribute]
int main(array<System::String^> ^args)
{
/* Enabling Windows XP visual effects before any controls are created */
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Application::Run(gcnew CWndMain());
return 0;
}

20
WinTN3270.sln Normal file
View File

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinTN3270", "WinTN3270.vcxproj", "{7E3C3C84-0CB0-4D5E-A97D-DFCFE401AFE4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7E3C3C84-0CB0-4D5E-A97D-DFCFE401AFE4}.Debug|Win32.ActiveCfg = Debug|Win32
{7E3C3C84-0CB0-4D5E-A97D-DFCFE401AFE4}.Debug|Win32.Build.0 = Debug|Win32
{7E3C3C84-0CB0-4D5E-A97D-DFCFE401AFE4}.Release|Win32.ActiveCfg = Release|Win32
{7E3C3C84-0CB0-4D5E-A97D-DFCFE401AFE4}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

312
WinTN3270.vcproj Normal file
View File

@ -0,0 +1,312 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="WinTN3270"
ProjectGUID="{7E3C3C84-0CB0-4D5E-A97D-DFCFE401AFE4}"
RootNamespace="WinTN3270"
Keyword="ManagedCProj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
ManagedExtensions="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(NoInherit)"
LinkIncremental="2"
GenerateDebugInformation="true"
AssemblyDebug="1"
SubSystem="2"
EntryPointSymbol="main"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
ManagedExtensions="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(NoInherit)"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
EntryPointSymbol="main"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
<AssemblyReference
RelativePath="System.dll"
AssemblyName="System, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
/>
<AssemblyReference
RelativePath="System.Data.dll"
AssemblyName="System.Data, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86"
/>
<AssemblyReference
RelativePath="System.Drawing.dll"
AssemblyName="System.Drawing, Version=2.0.0.0, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"
/>
<AssemblyReference
RelativePath="System.Windows.Forms.dll"
AssemblyName="System.Windows.Forms, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
/>
<AssemblyReference
RelativePath="System.XML.dll"
AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
/>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\AssemblyInfo.cpp"
>
</File>
<File
RelativePath=".\C3270Char.cpp"
>
</File>
<File
RelativePath=".\CClient3270.cpp"
>
</File>
<File
RelativePath=".\CEbcdicTranslator.cpp"
>
</File>
<File
RelativePath=".\CTelnetClient.cpp"
>
</File>
<File
RelativePath=".\CWndMain.cpp"
>
</File>
<File
RelativePath=".\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\WinTN3270.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\C3270Char.h"
>
</File>
<File
RelativePath=".\CClient3270.h"
>
</File>
<File
RelativePath=".\CEbcdicTranslator.h"
>
</File>
<File
RelativePath=".\CTelnetClient.h"
>
</File>
<File
RelativePath=".\CWndMain.h"
FileType="3"
>
<File
RelativePath=".\CWndMain.resX"
SubType="Designer"
>
</File>
</File>
<File
RelativePath=".\IBM3270.h"
>
</File>
<File
RelativePath=".\resource.h"
>
</File>
<File
RelativePath=".\stdafx.h"
>
</File>
<File
RelativePath=".\TelnetProtocol.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath=".\app.ico"
>
</File>
<File
RelativePath=".\app.rc"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

154
WinTN3270.vcxproj Normal file
View File

@ -0,0 +1,154 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{7E3C3C84-0CB0-4D5E-A97D-DFCFE401AFE4}</ProjectGuid>
<RootNamespace>WinTN3270</RootNamespace>
<Keyword>ManagedCProj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<CLRSupport>Pure</CLRSupport>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<CLRSupport>Pure</CLRSupport>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>
</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AssemblyDebug>true</AssemblyDebug>
<SubSystem>Windows</SubSystem>
<EntryPointSymbol>main</EntryPointSymbol>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>
</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EntryPointSymbol>main</EntryPointSymbol>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Reference Include="System">
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
</Reference>
<Reference Include="System.Data">
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
</Reference>
<Reference Include="System.Drawing">
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
</Reference>
<Reference Include="System.Windows.Forms">
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
</Reference>
<Reference Include="System.Xml">
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
</Reference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="AssemblyInfo.cpp" />
<ClCompile Include="C3270Char.cpp" />
<ClCompile Include="CClient3270.cpp" />
<ClCompile Include="CEbcdicTranslator.cpp" />
<ClCompile Include="CTelnetClient.cpp" />
<ClCompile Include="CWndMain.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="WinTN3270.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="C3270Char.h" />
<ClInclude Include="CClient3270.h" />
<ClInclude Include="CEbcdicTranslator.h" />
<ClInclude Include="CTelnetClient.h" />
<ClInclude Include="CWndMain.h">
<FileType>CppForm</FileType>
</ClInclude>
<ClInclude Include="IBM3270.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="TelnetProtocol.h" />
</ItemGroup>
<ItemGroup>
<None Include="app.ico" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="app.rc" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="CWndMain.resX">
<DependentUpon>CWndMain.h</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

BIN
app.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

63
app.rc Normal file
View File

@ -0,0 +1,63 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon placed first or with lowest ID value becomes application icon
LANGUAGE 9, 1
#pragma code_page(1252)
1 ICON "app.ico"
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
"\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

3
resource.h Normal file
View File

@ -0,0 +1,3 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by app.rc

7
stdafx.cpp Normal file
View File

@ -0,0 +1,7 @@
// stdafx.cpp : source file that includes just the standard includes
// WinTN3270.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"

6
stdafx.h Normal file
View File

@ -0,0 +1,6 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
#pragma once
#include <windows.h>