windows-nt/Source/XPSP1/NT/net/tcpip/services/telnet/client/commands.c
2020-09-26 16:20:57 +08:00

1384 lines
36 KiB
C

/*
commands.c
Copyright (c) Microsoft Corporation. All rights reserved.
Implementation of Telnet Commands
*/
#pragma warning( disable: 4201 )
#pragma warning( disable: 4100 )
#include <windows.h> /* required for all Windows applications */
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include "commands.h"
#include "WinTel.h" /* specific to this program */
#include "debug.h"
#include "trmio.h"
#include "telnet.h"
extern WI gwi;
extern HINSTANCE ghInstance;
extern HANDLE g_hRemoteNEscapeModeDataSync;
extern HANDLE g_hCaptureConsoleEvent;
extern WCHAR g_szKbdEscape[];
extern BOOL g_bIsEscapeCharValid;
extern BOOL bDoVtNTFirstTime;
extern BOOL fPrintMessageToSessionConsole;
BOOL bOnlyOnce = 1;
BOOL bBufferSizeChanged = 0;
BOOL bWindowSizeChanged = 0;
BOOL bMaxWindow = 0;
extern SMALL_RECT srOldClientWindow;
extern TCHAR g_szLogFile[];
extern g_fSentWillNaws;
void SetWindowSize( HANDLE );
void GetErrMsgString( DWORD, LPTSTR* );
BOOL StuffEscapeIACs( PUCHAR* ppBufDest, UCHAR bufSrc[], DWORD* pdwSize );
void ConvertAndSendVTNTData( LPTSTR pData, int iLen );
void *SfuZeroMemory(
void *ptr,
unsigned int cnt
)
{
volatile char *vptr = (volatile char *)ptr;
while (cnt)
{
*vptr = 0;
vptr ++;
cnt --;
}
return ptr;
}
BOOL PromptUser()
{
DWORD dwLength = 1;
INPUT_RECORD irRec;
ResetEvent( g_hCaptureConsoleEvent );
ui.bPromptForNtlm = TRUE;
irRec.EventType = FOCUS_EVENT;
irRec.Event.FocusEvent.bSetFocus = TRUE;
WriteConsoleInput( gwi.hInput, &irRec, dwLength, &dwLength );
WaitForSingleObject( g_hCaptureConsoleEvent, INFINITE );
return ui.bSendCredsToRemoteSite;
}
//NULL as the last arg is a MUST when you are using Write function
void Write(LPTSTR lpszFmtStr, ...)
{
DWORD dwWritten;
DWORD dwSize = 0;
va_list vaArgList;
TCHAR *szBuf = NULL;
TCHAR *szArg = lpszFmtStr;
if( !lpszFmtStr )
{
return;
}
va_start( vaArgList, lpszFmtStr );
while( szArg )
{
dwSize += wcslen( szArg );
szArg = va_arg( vaArgList, LPWSTR );
}
va_end( vaArgList );
szBuf = ( TCHAR *) malloc( ( dwSize + 1 ) * sizeof( TCHAR ) );
if( !szBuf )
{
return;
}
szBuf[dwSize] = 0;
va_start( vaArgList, lpszFmtStr );
//PREFIX gives "untrusted function". We want to use _vsntprintf(). Won't fix.
_vsntprintf( szBuf, dwSize,lpszFmtStr, vaArgList );
va_end( vaArgList );
WriteConsole(gwi.hOutput, szBuf, _tcslen(szBuf), &dwWritten, NULL);
free( szBuf );
}
void WriteMessage( DWORD dwMsgId, WCHAR szEnglishString[] )
{
WCHAR szMsg[ MAX_STRING_LENGTH ];
if( !LoadString( ghInstance, dwMsgId, szMsg, MAX_STRING_LENGTH ) )
{
lstrcpyn( szMsg, szEnglishString, MAX_STRING_LENGTH - sizeof(WCHAR) );
}
Write( szMsg, NULL );
}
void FreeLoggingDataStructs()
{
if( g_rgciCharInfo != NULL )
(void)LocalFree( (HLOCAL)g_rgciCharInfo );
if (g_rgchRow != NULL)
(void)LocalFree( (HLOCAL)g_rgchRow );
g_rgchRow = NULL;
g_rgciCharInfo = NULL;
}
BOOL CloseTelnetSession(LPTSTR szCommand)
{
CONSOLE_SCREEN_BUFFER_INFO csbInfo;
if( FGetCodeMode(eCodeModeIMEFarEast) && bOnlyOnce )
{
bOnlyOnce = 0;
GetConsoleScreenBufferInfo( g_hSessionConsoleBuffer, &csbInfo );
if( bBufferSizeChanged )
{
csbInfo.dwSize.Y -= 1;
SetConsoleScreenBufferSize( g_hSessionConsoleBuffer,
csbInfo.dwSize );
}
if( bWindowSizeChanged )
{
csbInfo.srWindow.Bottom -= 1;
SetConsoleWindowInfo( g_hSessionConsoleBuffer, TRUE,
&csbInfo.srWindow);
}
}
bDoVtNTFirstTime = 1;
if( fConnected )
{
fConnected = FHangupConnection(&gwi, &(gwi.nd));
}
if( ui.bLogging )
{
FreeLoggingDataStructs();
}
ui.dwMaxRow = 0;
ui.dwMaxCol = 0;
srOldClientWindow.Left = srOldClientWindow.Right = 0;
srOldClientWindow.Top = srOldClientWindow.Bottom = 0;
SetEvent( g_hRemoteNEscapeModeDataSync );
SetConsoleTitle( szAppName );
g_fSentWillNaws = FALSE; //so that it does naws when we connect again.
return FALSE;
}
extern CHAR* rgchTermType[];
BOOL DisplayParameters(LPTSTR szCommand)
{
TCHAR szTermType[81];
DWORD dwLen = 0;
SfuZeroMemory(szTermType, sizeof(szTermType));
if( g_bIsEscapeCharValid )
{
Write( g_szKbdEscape, NULL );
}
else
{
TCHAR szMsg[ MAX_STRING_LENGTH ];
LoadString( ghInstance, IDS_NO_ESCAPE , szMsg, MAX_STRING_LENGTH );
Write( szMsg, NULL );
}
if ( ui.bWillAUTH )
Write( szWillAuth, NULL );
else
Write( szWontAuth, NULL );
if( ui.fDebug & fdwLocalEcho )
Write( szLocalEchoOn, NULL );
else
Write( szLocalEchoOff, NULL );
if( ui.bLogging )
{
TCHAR szFileNameTitle[ MAX_STRING_LENGTH + 1 ];
WriteMessage( IDS_LOGGING_ON, ( LPTSTR ) TEXT( MSG_LOGGING_ON ) );
LoadString( ghInstance, IDS_LOGFILE_NAME, szFileNameTitle, MAX_STRING_LENGTH );
Write( szFileNameTitle, g_szLogFile, NULL );
}
if( ui.dwCrLf )
{
WriteMessage( IDS_CRLF, ( LPTSTR ) _T( MSG_CRLF ) );
}
else
{
WriteMessage( IDS_CR, ( LPTSTR ) _T( MSG_CR ) );
}
if( g_bSendBackSpaceAsDel )
{
WriteMessage( IDS_BACKSPACEASDEL, ( LPTSTR ) _T( MSG_BACKSPACEASDEL ) );
}
if( g_bSendDelAsBackSpace )
{
WriteMessage( IDS_DELASBACKSPACE, ( LPTSTR ) _T( MSG_DELASBACKSPACE ) );
}
if( (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80)) &&
FIsVT80(&gwi.trm) && (gwi.trm.RequestedTermType != TT_VTNT) )
{
int i =0;
for(i=0 ; i<NUMBER_OF_KANJI ; ++i)
{
if( gwi.trm.dwKanjiFlags & KanjiList[i].KanjiEmulationID )
{
Write( szVT100KanjiEmulation, NULL );
Write( KanjiList[i].KanjiDescription, NULL );
break;
}
}
Write( TEXT("\n"), NULL );
}
{
DWORD dwSize = 0;
WCHAR wchTemp[1] = {0L};
dwSize = GetEnvironmentVariable( TEXT( SFUTLNTMODE ), wchTemp, 0 );
if( dwSize > 0 )
{
TCHAR *szMode = NULL;
szMode = ( TCHAR * ) malloc( ( dwSize + 1 )* sizeof( TCHAR ) );
if( szMode != NULL )
{
dwSize = GetEnvironmentVariable( TEXT( SFUTLNTMODE ), szMode, dwSize + 1 );
if( _tcsicmp( szMode, TEXT( CONSOLE )) == 0 )
{
dwSize = 0; //indicating console mode
}
else
{
WriteMessage( IDS_CURRENT_MODE, ( LPTSTR )TEXT( MSG_CURRENT_MODE ) );
WriteMessage( IDS_STREAM_ONLY, ( LPTSTR )TEXT( MSG_STREAM_ONLY ) );
}
free( szMode );
}
}
if( dwSize == 0 )
{
//console mode
WriteMessage( IDS_CURRENT_MODE, ( LPTSTR )TEXT( MSG_CURRENT_MODE ) );
WriteMessage( IDS_CONSOLE_ONLY, ( LPTSTR )TEXT( MSG_CONSOLE_ONLY ) );
}
}
//#if defined(FE_IME)
// if( ui.fDebug & fdwEnableIMESupport )
// {
// Write( szEnableIMEOn, NULL );
// }
//#endif /* FE_IME */
dwLen = sizeof(szTermType)/sizeof(WCHAR);
szTermType[dwLen -1] = 0;
_snwprintf( szTermType,dwLen -1, ( LPTSTR )TEXT("%S"), rgchTermType[gwi.trm.RequestedTermType] );
Write( szPrefTermType, szTermType, NULL );
// when we are connected we need to say what we are connected at.
if ( fConnected && gwi.trm.SentTermType != TT_UNKNOWN )
{
_snwprintf( szTermType,(sizeof(szTermType)/sizeof(WCHAR))-1, ( LPTSTR )TEXT("%S"), rgchTermType[gwi.trm.SentTermType]);
Write( szNegoTermType, szTermType, NULL );
}
return FALSE;
}
/* This initialization happens on every OpenTelnetSession()
and the meemory is freed on every CloseTelnetSession() */
BOOL InitLoggingDataStructs()
{
UINT uiSize = 0;
if( g_rgchRow )
{
//This is needed because rows and cols may have changed
FreeLoggingDataStructs();
}
uiSize = (UINT)(sizeof(CHAR_INFO) * ui.dwMaxCol);
if( FGetCodeMode( eCodeModeFarEast ) )
{
uiSize *= 3; // accounting for a lot of multi byte chars
}
g_rgciCharInfo = (PCHAR_INFO)LocalAlloc(LPTR, uiSize );
g_rgchRow = (UCHAR *)LocalAlloc(LPTR, uiSize );
if ( !g_rgchRow || !g_rgciCharInfo )
{
ui.bLogging = FALSE;
return FALSE;
}
return TRUE;
}
BOOL CloseLogging()
{
CloseHandle(ui.hLogFile);
ui.hLogFile = NULL;
return TRUE;
}
BOOL StopLogging()
{
ui.bLogging = FALSE;
FreeLoggingDataStructs();
return TRUE;
}
BOOL InitLogFile( LPTSTR szCommand )
{
if( ui.hLogFile )
{
CloseLogging( );
}
ui.hLogFile = CreateFile( szCommand, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL,
CREATE_ALWAYS, 0, NULL);
if (ui.hLogFile == INVALID_HANDLE_VALUE)
{
LPWSTR szErrMsg = NULL;
ui.bLogging = FALSE;
ui.hLogFile = NULL;
GetErrMsgString( GetLastError(), &szErrMsg );
Write( szErrMsg, L"\r\n", NULL );
LocalFree( szErrMsg );
return FALSE;
}
return TRUE;
}
BOOL StartLogging( )
{
ui.bLogging = FALSE;
if( !ui.hLogFile ) //If we have valid logfile
{
return FALSE;
}
ui.bLogging = TRUE;
if( ui.dwMaxRow != 0 && ui.dwMaxCol != 0 )
{
InitLoggingDataStructs();
}
return TRUE;
}
INT GetRequestedTermType( LPTSTR pszTerm )
{
if( !_tcsicmp( pszTerm, ( LPTSTR )TEXT("ansi") ))
return 0;
if( !_tcsicmp( pszTerm, ( LPTSTR )TEXT("vt100") ))
return 1;
if( !_tcsicmp( pszTerm, ( LPTSTR )TEXT("vt52") ))
return 2;
if( !_tcsicmp( pszTerm, ( LPTSTR )TEXT("vtnt") ))
return 3;
return -1;
}
void SqueezeWhiteSpace( TCHAR s[] )
{
INT i,j;
if( s == NULL )
{
return;
}
for( i = 0, j= 0; s[i] != _T('\0'); i++ )
if( !iswspace( s[i] ) )
{
s[j++] = s[i];
}
s[j] = _T('\0');
}
void RemoveLeadingNTrailingWhiteSpaces( LPTSTR *pOption )
{
DWORD dwIndex = 0;
if( *pOption == NULL )
{
return;
}
dwIndex = wcslen( *pOption );
if( dwIndex <= 0 )
{
return;
}
while( iswspace( (*pOption)[ dwIndex - 1 ] ) && dwIndex > 0 )
{
dwIndex--;
}
(*pOption)[ dwIndex ] = L'\0';
while( iswspace( *( *pOption ) ) )
{
(*pOption)++;
}
}
BOOL SendOptions( LPTSTR pOption )
{
if( pOption == NULL )
{
WriteMessage( IDS_SEND_FORMAT, ( LPTSTR )TEXT( MSG_SEND_FORMAT ) );
return FALSE;
}
RemoveLeadingNTrailingWhiteSpaces( &pOption );
if( *pOption== _T('?') )
{
WriteMessage( IDS_SEND_HELP, ( LPTSTR )TEXT( MSG_SEND_HELP ) );
return FALSE;
}
if( !fConnected )
{
WriteMessage( IDS_NOT_CONNECTED, ( LPTSTR )TEXT( MSG_NOT_CONNECTED ) );
return FALSE;
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("AO") ) )
{
/* Our server does nothing on receiving AO. This is for other servers */
FSendTelnetCommands(gwi.hwnd, (char)AO);
WriteMessage( IDS_SENT_AO, ( LPTSTR )TEXT( MSG_SENT_AO ) );
return FALSE;
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("AYT") ) )
{
FSendTelnetCommands(gwi.hwnd, (char)AYT);
WriteMessage( IDS_SENT_AYT, ( LPTSTR )TEXT( MSG_SENT_AYT ) );
return FALSE;
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("ESC") ) )
{
if(gwi.trm.CurrentTermType == TT_VTNT)
{
ConvertAndSendVTNTData(&g_chEsc,1);
}
else
{
FSendChars( gwi.hwnd, &g_chEsc, sizeof( g_chEsc ) / sizeof( WCHAR ) );
}
WriteMessage( IDS_SENT_ESC, ( LPTSTR )TEXT( MSG_SENT_ESC ) );
return FALSE;;
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("IP") ) )
{
FSendTelnetCommands(gwi.hwnd, (char)IP);
WriteMessage( IDS_SENT_IP, ( LPTSTR )TEXT( MSG_SENT_IP ) );
return FALSE;
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("SYNCH") ) )
{
FSendSynch( gwi.hwnd );
WriteMessage( IDS_SENT_SYNCH, ( LPTSTR )TEXT( MSG_SENT_SYNCH ) );
return FALSE;
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("BRK") ) )
{
FSendTelnetCommands(gwi.hwnd, (char)BREAK );
WriteMessage( IDS_SENT_BRK, ( LPTSTR )TEXT( MSG_SENT_BRK ) );
return FALSE;
}
//If none of the above send as it is
{
WCHAR szMsg[ MAX_STRING_LENGTH + 1 ];
if(gwi.trm.CurrentTermType == TT_VTNT)
{
ConvertAndSendVTNTData(pOption,wcslen(pOption));
}
else
{
FSendChars( gwi.hwnd, pOption, wcslen( pOption ) );
}
if( !LoadString( ghInstance, IDS_SENT_CHARS, szMsg, MAX_STRING_LENGTH ) )
{
wcscpy( szMsg, TEXT( MSG_SENT_CHARS ) ); //no overflow. LoadString will return NULL terminated string.
}
Write( szMsg, pOption, NULL );
}
return FALSE;
}
/*++ If the data to be sent to the server is VTNT data, it cannot be sent as it is. This function
will convert the given string ( pData ) into INPUT_RECORDS and send it through the socket. This
is needed since the server expects VTNT data in INPUT_RECORD format and not in characters.
--*/
void ConvertAndSendVTNTData( LPTSTR pData, int iLen )
{
INPUT_RECORD sInputRecord;
PUCHAR destBuf = NULL;
DWORD dwSize = 0;
int iIndex = 0;
while(iLen)
{
sInputRecord.EventType = KEY_EVENT;
sInputRecord.Event.KeyEvent.bKeyDown = TRUE;
sInputRecord.Event.KeyEvent.uChar.UnicodeChar = pData[iIndex];
dwSize = sizeof( INPUT_RECORD );
if( !StuffEscapeIACs( &destBuf, (PUCHAR) &sInputRecord, &dwSize ) )
{
FWriteToNet(&gwi, (char *)&sInputRecord, sizeof(INPUT_RECORD));
}
else
{
FWriteToNet( &gwi, ( CHAR* )destBuf, dwSize );
dwSize = 0;
}
iIndex++;
iLen --;
}
if(destBuf)
free( destBuf );
}
BOOL SetOptions( LPTSTR pOption )
{
TCHAR szLoggingOn[ MAX_STRING_LENGTH ];
if( pOption == NULL )
{
Write( szSetFormat, NULL );
return FALSE;
}
RemoveLeadingNTrailingWhiteSpaces( &pOption );
if( *pOption== _T('?') )
{
Write( szSetHelp, NULL );
return FALSE;
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("BSASDEL") ) )
{
g_bSendBackSpaceAsDel = TRUE;
WriteMessage( IDS_BACKSPACEASDEL, ( LPTSTR )TEXT( MSG_BACKSPACEASDEL ) );
return FALSE;
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("CRLF") ) )
{
SetLineMode( &( gwi.trm ) );
ui.dwCrLf=TRUE;
WriteMessage( IDS_CRLF, ( LPTSTR )TEXT( MSG_CRLF ) );
return FALSE;
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("DELASBS") ) )
{
g_bSendDelAsBackSpace = TRUE;
WriteMessage( IDS_DELASBACKSPACE, ( LPTSTR )TEXT( MSG_DELASBACKSPACE ) );
return FALSE;
}
if( !_tcsnicmp( pOption, ( LPTSTR )TEXT("MODE"), wcslen( ( LPTSTR )TEXT("MODE") ) )
&& iswspace( *( pOption + wcslen( ( LPTSTR )TEXT("MODE") ) ) ) )
{
TCHAR* pMode = NULL;
pOption += wcslen( ( LPTSTR )TEXT("MODE") );
pMode = _tcstok( pOption, ( LPTSTR )_T(" \t") );
if( pMode )
{
SqueezeWhiteSpace( pMode );
if( pMode[ 0 ] != L'\0' )
{
if( !_tcsicmp( pMode, ( LPTSTR )TEXT( STREAM )) )
{
if( !SetEnvironmentVariable( TEXT( SFUTLNTMODE ), TEXT( STREAM ) ) )
{
DWORD dwError = 0;
ASSERT( 0 );
dwError = GetLastError();
}
WriteMessage( IDS_STREAM, ( LPTSTR )TEXT( MSG_STREAM ) );
return FALSE;
}
else if( !_tcsicmp( pMode, ( LPTSTR )TEXT( CONSOLE ) ) )
{
if( !SetEnvironmentVariable( TEXT( SFUTLNTMODE ), TEXT( CONSOLE ) ) )
{
DWORD dwError = 0;
ASSERT( 0 );
dwError = GetLastError();
}
WriteMessage( IDS_CONSOLE, ( LPTSTR )TEXT( MSG_CONSOLE ) );
return FALSE;
}
else
{
WriteMessage(IDS_SUPPORTED_MODES, (LPTSTR) TEXT ( MSG_SUPPORTED_MODES) );
return FALSE;
}
}
}
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("NTLM") ) )
{
ui.bWillAUTH = 1;
Write( szWillAuth, NULL );
return FALSE;
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("LOCALECHO") ) )
{
ui.fDebug |= fdwLocalEcho;
Write( szLocalEchoOn, NULL );
return FALSE;
}
if( !_tcsnicmp( pOption, ( LPTSTR )TEXT("LOGFILE"),
wcslen( ( LPTSTR )TEXT("LOGFILE") ) )
&& iswspace( *( pOption + wcslen( ( LPTSTR )TEXT("LOGFILE") ) ) ) )
{
TCHAR szMsg[ MAX_STRING_LENGTH ];
TCHAR* pTerm = NULL;
pOption += wcslen( ( LPTSTR )TEXT("LOGFILE") );
pTerm = _tcstok( pOption, ( LPTSTR )_T(" \t") );
if( pTerm )
{
SqueezeWhiteSpace( pTerm );
if( !InitLogFile( pTerm ) )
{
LoadString( ghInstance, IDS_BAD_LOGFILE, szMsg, MAX_STRING_LENGTH );
Write( szMsg, NULL );
return FALSE;
}
}
LoadString( ghInstance, IDS_LOGFILE_NAME, szMsg, MAX_STRING_LENGTH );
Write( szMsg, pTerm, NULL );
wcsncpy( g_szLogFile, pTerm, MAX_PATH );
StartLogging( );
LoadString( ghInstance, IDS_LOGGING_ON, szLoggingOn, MAX_STRING_LENGTH );
Write( szLoggingOn, NULL );
return FALSE;
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("LOGGING") ) )
{
if( StartLogging() )
{
LoadString( ghInstance, IDS_LOGGING_ON, szLoggingOn, MAX_STRING_LENGTH );
}
else
{
LoadString( ghInstance, IDS_NO_LOGFILE, szLoggingOn, MAX_STRING_LENGTH );
}
Write( szLoggingOn, NULL );
return FALSE;
}
if( ( !_tcsnicmp( pOption, ( LPTSTR )TEXT("ESCAPE"), wcslen( ( LPTSTR )TEXT("ESCAPE") ) ) )
&& ( iswspace( *( pOption + wcslen( ( LPTSTR )TEXT("ESCAPE") ) ) ) ||
*( pOption + wcslen( ( LPTSTR )TEXT("ESCAPE") ) ) == L'\0' ) )
{
TCHAR* pTerm = NULL;
pOption += wcslen( ( LPTSTR )TEXT("ESCAPE") );
pTerm = _tcstok( pOption, ( LPTSTR )_T(" \t") );
if( pTerm )
{
SqueezeWhiteSpace( pTerm );
if( pTerm[ 0 ] != L'\0' )
{
SetEscapeChar( pTerm[ 0 ] );
}
}
g_bIsEscapeCharValid = TRUE;
Write( g_szKbdEscape, NULL );
return FALSE;
}
if( !_tcsnicmp( pOption, ( LPTSTR )TEXT("TERM"),
wcslen( ( LPTSTR )TEXT("TERM") ) )
&& iswspace( *( pOption + wcslen( ( LPTSTR )TEXT("TERM") ) ) ) )
{
TCHAR* pTerm = NULL;
pOption += wcslen( ( LPTSTR )TEXT("TERM") );
pTerm = _tcstok( pOption, ( LPTSTR )_T(" \t") );
if( pTerm )
{
int iTermType;
SqueezeWhiteSpace( pTerm );
if( (iTermType = GetRequestedTermType( pTerm )) < 0 )
{
Write( szSupportedTerms, NULL );
return FALSE;
}
else
{
gwi.trm.RequestedTermType = iTermType;
}
Write( szPrefTermType, pTerm, NULL );
if (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80))
{
ui.fDebug &= ~(fdwVT52Mode|fdwVT80Mode);
ui.fDebug &= ~(fdwKanjiModeMask);
ClearVT80(&gwi.trm);
ClearKanjiStatus(&gwi.trm, CLEAR_ALL);
ClearKanjiFlag(&gwi.trm);
SetupCharSet(&gwi.trm);
}
}
return FALSE;
}
if((GetACP() == JAP_CODEPAGE ) && (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80)) &&
!_tcsnicmp( pOption, ( LPTSTR )TEXT("CODESET"), wcslen( ( LPTSTR )TEXT("CODESET") ) )
&& iswspace( *( pOption + wcslen( ( LPTSTR )TEXT("CODESET") ) ) ) )
{
TCHAR* pCodeset = NULL;
pOption += wcslen( ( LPTSTR )TEXT("CODESET") );
RemoveLeadingNTrailingWhiteSpaces( &pOption );
pCodeset = pOption;
if( pCodeset )
{
int i;
for(i=0 ; i<NUMBER_OF_KANJI ; ++i)
{
if(!_tcsicmp(KanjiList[i].KanjiDescription, pCodeset)) {
SetVT80(&gwi.trm);
ui.fDebug &= ~fdwKanjiModeMask;
ClearKanjiFlag(&gwi.trm);
ui.fDebug |= KanjiList[i].KanjiID;
ui.fDebug |= fdwVT80Mode;
SetKanjiMode(&gwi.trm,KanjiList[i].KanjiEmulationID);
SetupCharSet(&gwi.trm);
Write( szVT100KanjiEmulation, NULL );
Write( KanjiList[i].KanjiDescription, NULL );
Write( ( LPTSTR ) _T( "\r\n" ), NULL );
return FALSE;
}
}
if( i >= NUMBER_OF_KANJI )
{
WriteMessage(IDS_SET_CODESET_FORMAT, (LPTSTR) TEXT ( MSG_SET_CODESET_FORMAT) );
}
}
return FALSE;
}
Write( szSetFormat, NULL );
return FALSE;
}
BOOL UnsetOptions( LPTSTR pOption )
{
if ( pOption == NULL )
{
Write( szUnsetFormat, NULL );
return FALSE;
}
RemoveLeadingNTrailingWhiteSpaces( &pOption );
if ( *pOption == _T('?') )
{
Write( szUnsetHelp, NULL );
return FALSE;
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("BSASDEL") ) )
{
g_bSendBackSpaceAsDel = FALSE;
WriteMessage( IDS_BACKSPACEASBACKSPACE, ( LPTSTR )TEXT( MSG_BACKSPACEASBACKSPACE ) );
return FALSE;
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("CRLF") ) )
{
ClearLineMode( &( gwi.trm ) );
ui.dwCrLf= FALSE;
WriteMessage( IDS_CR, ( LPTSTR )TEXT( MSG_CR ) );
return FALSE;
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("DELASBS") ) )
{
g_bSendDelAsBackSpace = FALSE;
WriteMessage( IDS_DELASDEL, ( LPTSTR )TEXT( MSG_DELASDEL ) );
return FALSE;
}
if ( !_tcsicmp( pOption, ( LPTSTR )TEXT("NTLM") ) )
{
ui.bWillAUTH = 0;
Write( szWontAuth, NULL );
return FALSE;
}
if ( !_tcsicmp( pOption, ( LPTSTR )TEXT("LOCALECHO") ) )
{
ui.fDebug &= ~fdwLocalEcho;
Write( szLocalEchoOff, NULL );
return FALSE;
}
if( !_tcsicmp( pOption, ( LPTSTR )TEXT("LOGGING") ) )
{
TCHAR szLoggingOff[ MAX_STRING_LENGTH ];
LoadString( ghInstance, IDS_LOGGING_OFF, szLoggingOff, MAX_STRING_LENGTH );
Write( szLoggingOff, NULL );
StopLogging();
return FALSE;
}
if ( !_tcsicmp( pOption, ( LPTSTR )TEXT("ESCAPE") ) )
{
TCHAR szMsg[ MAX_STRING_LENGTH ];
g_bIsEscapeCharValid = FALSE;
LoadString( ghInstance, IDS_NO_ESCAPE , szMsg, MAX_STRING_LENGTH );
Write( szMsg, NULL );
return FALSE;
}
if ((GetACP() == JAP_CODEPAGE ) && (FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80)) && !_tcsicmp( pOption, ( LPTSTR )TEXT("CODESET") ) )
{
TCHAR szNoEmulation[ MAX_STRING_LENGTH ];
ui.fDebug &= ~(fdwVT52Mode|fdwVT80Mode);
ui.fDebug &= ~(fdwKanjiModeMask);
ClearVT80(&gwi.trm);
ClearKanjiStatus(&gwi.trm, CLEAR_ALL);
ClearKanjiFlag(&gwi.trm);
SetupCharSet(&gwi.trm);
LoadString( ghInstance, IDS_NO_EMULATION, szNoEmulation, MAX_STRING_LENGTH );
Write( szNoEmulation, NULL );
return FALSE;
}
Write( szUnsetFormat, NULL );
return FALSE;
}
/*#if defined(FE_IME)
BOOL EnableIMEOptions( LPTSTR pOption )
{
do {
if ( pOption == NULL )
{
Write( szEnableIMEFormat, NULL );
break;
}
if ( *pOption == _T('?') )
{
Write( szEnableIMEHelp, NULL );
break;
}
if ( !_tcsicmp( pOption, TEXT("IME") ) )
{
ui.fDebug |= fdwEnableIMESupport;
break;
}
else
{
Write( szEnableIMEFormat, NULL );
break;
}
} while ( FALSE );
return FALSE;
}
BOOL DisableIMEOptions( LPTSTR pOption )
{
do {
if ( pOption == NULL )
{
Write( szDisableIMEFormat, NULL );
break;
}
if ( *pOption == _T('?') )
{
Write( szDisableIMEHelp, NULL );
break;
}
if ( !_tcsicmp( pOption, TEXT("IME") ) )
{
ui.fDebug &= ~(fdwEnableIMESupport);
break;
}
else
{
Write( szDisableIMEFormat, NULL );
break;
}
} while ( FALSE );
return FALSE;
}
**/
//#endif /* FE_IME */
//
// (a-roopb) Added below routine to fix to bug 1007
//
LPTSTR SkipLeadingWhiteSpaces( LPTSTR szCommand )
{
int i=0;
while( szCommand[i] && _istspace( szCommand[i] ) )
{
++i;
}
return szCommand+i;
}
extern DWORD HandleTelnetSession( WI* pwi );
void ClearInitialScreen( HANDLE hConsole )
{
DWORD dwNumWritten;
COORD dwWriteCoord;
dwWriteCoord.X = 0; dwWriteCoord.Y = 0;
FillConsoleOutputCharacter( hConsole,
' ', ( gwi.sbi.dwSize.X ) * ( gwi.sbi.dwSize.Y ),
dwWriteCoord, &dwNumWritten );
FillConsoleOutputAttribute( hConsole, gwi.sbi.wAttributes,
( gwi.sbi.dwSize.X ) * ( gwi.sbi.dwSize.Y ), dwWriteCoord,
&dwNumWritten );
}
//This sets a global variable with the port number
void GetPortNumber( )
{
CHAR szPortString[ cchMaxHostName ];
struct servent *serv;
rgService = TELNET_PORT ;
if( IsCharAlpha( g_szPortNameOrNo[0] ) )
{
_snprintf( szPortString,cchMaxHostName-1, "%lS", g_szPortNameOrNo );
if((serv = getservbyname( szPortString, "tcp")) != NULL)
{
rgService = htons( (SHORT)serv->s_port );
}
else
{
rgService = 0;
}
}
else if( IsCharAlphaNumeric( g_szPortNameOrNo[0] ) )
{
rgService = _ttoi( g_szPortNameOrNo );
}
return;
}
void PrepareForNAWS( )
{
// Now we need to set the correct sizes.
// ui.dwMaxRow = gwi.sbi.dwMaximumWindowSize.Y;
//ui.dwMaxCol = gwi.sbi.dwMaximumWindowSize.X;
//This change is meant for making the client provide scrolling
ui.dwMaxRow = gwi.sbi.dwSize.Y;
ui.dwMaxCol = gwi.sbi.dwSize.X;
}
BOOL OpenTelnetSession( LPTSTR pszCommand )
{
DWORD dwWritten;
DWORD dwRead;
LPTSTR pszPort;
LPTSTR pszHost;
CHAR szHstNam[MAX_PATH + 1] = { 0 };
WCHAR szTitleName[MAX_PATH + 2 + MAX_PATH ];
TCHAR szCommand[255] = { 0 };
DWORD dwMode = ( DWORD )-1;
COORD coOrgin = { 0, 0 };
gwi.eState=Connecting;
if( pszCommand == NULL )
{
WriteConsole( gwi.hOutput, szOpenTo, _tcslen(szOpenTo), &dwWritten,
NULL );
if( ReadConsole( gwi.hInput, szCommand,
( sizeof( szCommand ) /sizeof( TCHAR) )- sizeof( TCHAR ) , &dwRead, NULL ) )
{
// no input ??
if( dwRead == 2 )
{
WriteConsole( gwi.hOutput, szOpenUsage, _tcslen(szOpenUsage),
&dwWritten, NULL );
return FALSE;
}
}
else
{
//error ; do something ?
return FALSE;
}
// Null Terminate the string and remove the newline characters.
szCommand[ dwRead - 1 ] = 0;
szCommand[ dwRead - 2 ] = 0;
//
// (a-roopb) Added below 5 lines to fix to bug 1007
//
pszCommand = SkipLeadingWhiteSpaces( szCommand );
if( !_tcslen(pszCommand) )
{
WriteConsole( gwi.hOutput, szOpenUsage, _tcslen(szOpenUsage), &dwWritten, NULL );
return FALSE;
}
}
if ( fConnected )
{
CloseTelnetSession( NULL );
}
pszHost = _tcstok( pszCommand, ( LPTSTR )TEXT(" ") );
pszPort = _tcstok( NULL, ( LPTSTR )TEXT("") );
g_szPortNameOrNo[ 0 ] = 0;
if( pszPort != NULL )
{
_tcsncpy( g_szPortNameOrNo, pszPort , cchMaxHostName - 1);
}
GetPortNumber();
if(pszHost!=NULL)
{
_tcsncpy( rgchHostName, pszHost, min( _tcslen(pszHost)+1, cchMaxHostName - 1 ) );
}
else
{
return FALSE;
}
rgchHostName[cchMaxHostName - 1]= _T('\0');
// need to get the current window size before creating the session.
// This is needed both for NAWS negotiation and also for creating a matching
// session buffer.
GetConsoleScreenBufferInfo( g_hTelnetPromptConsoleBuffer, &gwi.sbi );
SetWindowSize( g_hSessionConsoleBuffer );
if( FGetCodeMode( eCodeModeIMEFarEast ) )
{
if( ( gwi.sbi.srWindow.Bottom - gwi.sbi.srWindow.Top + 1 )
== gwi.sbi.dwMaximumWindowSize.Y )
{
gwi.sbi.dwSize.Y -= 1;
gwi.sbi.srWindow.Bottom -= 1;
bMaxWindow = 1;
}
}
PrepareForNAWS();
if( ui.bLogging )
{
if( !InitLoggingDataStructs() )
{
return FALSE;
}
}
//
// (a-roopb) Hack to fix bug 1092. Users may set the terminal emulation type
// before session start and DoTermReset sets the emulation types etc. to
// defaults. So we reset the emulation type after call to DoTermReset.
//
if ((FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80)) && ui.fDebug & fdwKanjiModeMask)
{
dwMode = ui.fDebug & fdwKanjiModeMask;
}
else
{
dwMode = ( DWORD )-1;
}
DoTermReset(&gwi, &gwi.trm);
//
// (a-roopb) Hack to fix bug 1092. Users may set the terminal emulation type
// before session start and DoTermReset sets the emulation types etc. to
// default. So we reset the emulation type again here to user chosen one.
//
if((FGetCodeMode(eCodeModeFarEast) && FGetCodeMode(eCodeModeVT80)) &&
!(dwMode & 0x80000000) )
{
int i;
for( i=0 ; i<NUMBER_OF_KANJI ; ++i )
{
if( dwMode == KanjiList[i].KanjiID )
{
SetVT80(&gwi.trm);
ui.fDebug &= ~fdwKanjiModeMask;
ClearKanjiFlag(&gwi.trm);
ui.fDebug |= KanjiList[i].KanjiID;
SetKanjiMode(&gwi.trm,KanjiList[i].KanjiEmulationID);
SetupCharSet(&gwi.trm);
break;
}
}
}
if( fPrintMessageToSessionConsole )
{
gwi.hOutput = g_hSessionConsoleBuffer;
}
WriteConsole( gwi.hOutput, szConnecting, _tcslen(szConnecting), &dwWritten, NULL);
WriteConsole( gwi.hOutput, pszHost, _tcslen(pszHost), &dwWritten, NULL);
WriteConsole( gwi.hOutput, ( LPTSTR )TEXT("..."), _tcslen( ( LPTSTR )TEXT("...")), &dwWritten, NULL);
WideCharToMultiByte( GetACP(), 0, pszHost, -1, szHstNam, MAX_PATH, NULL, NULL );
wcsncpy( szTitleName, szAppName, MAX_PATH );
szTitleName[ MAX_PATH + 1 ] = L'\0';
wcscat( szTitleName, ( LPTSTR )L" " ); // no overflow
wcsncat( szTitleName, pszHost, MAX_PATH );
szTitleName[ MAX_PATH + 1 + MAX_PATH ] = L'\0';
SetConsoleTitle( szTitleName );
fConnected = FConnectToServer(&gwi, szHstNam, &(gwi.nd));
if( fPrintMessageToSessionConsole )
{
fPrintMessageToSessionConsole = FALSE;
gwi.hOutput = g_hTelnetPromptConsoleBuffer;
}
if( fConnected == TRUE )
{
COORD dwSizeIME = gwi.sbi.dwSize;
SMALL_RECT rectIME;
if( FGetCodeMode(eCodeModeIMEFarEast) )
{
dwSizeIME.X = gwi.sbi.dwSize.X;
dwSizeIME.Y = gwi.sbi.dwSize.Y += 1;
}
if( FGetCodeMode(eCodeModeIMEFarEast) )
{
if( !SetConsoleScreenBufferSize( g_hSessionConsoleBuffer,
dwSizeIME ) )
{
fConnected = FHangupConnection(&gwi, &(gwi.nd));
return FALSE;
}
}
ClearInitialScreen(g_hSessionConsoleBuffer);
memcpy( &rectIME, &gwi.sbi.srWindow, sizeof(SMALL_RECT) ); // no overflow
if( FGetCodeMode(eCodeModeIMEFarEast) )
{
rectIME.Bottom += 1;
//
// Since we are increasing the size, we need to first resize the console window
// and then the buffer otherwise it won't work
//
bWindowSizeChanged =
SetConsoleWindowInfo( g_hSessionConsoleBuffer, TRUE, &rectIME );
bBufferSizeChanged =
SetConsoleScreenBufferSize( g_hSessionConsoleBuffer, dwSizeIME );
if( bMaxWindow )
{
bWindowSizeChanged = bBufferSizeChanged = 0;
}
}
SetConsoleCursorPosition( g_hSessionConsoleBuffer, coOrgin );
srOldClientWindow = rectIME;
gwi.nd.fRespondedToWillEcho = FALSE;
gwi.nd.fRespondedToWillSGA = FALSE;
gwi.nd.fRespondedToDoAUTH = FALSE;
gwi.nd.fRespondedToDoNAWS = FALSE;
gwi.trm.dwCurChar = 0;
gwi.trm.dwCurLine = 0;
HandleTelnetSession(&gwi);
Write( ( LPTSTR )TEXT("\r\n"), NULL );
}
return FALSE;
}
BOOL CopyNPastePromptScreen( )
{
PCHAR_INFO pcInfo = NULL;
CONSOLE_SCREEN_BUFFER_INFO csbInfoOfPrompt;
COORD coSize = { 0, 0 };
COORD coBufferStart = { 0, 0 };
SMALL_RECT srRead = { 0, 0, 0, 0 };
SHORT wScreenSize = 0;
if( GetConsoleScreenBufferInfo( g_hTelnetPromptConsoleBuffer, &csbInfoOfPrompt ) )
{
wScreenSize = ( SHORT )( csbInfoOfPrompt.srWindow.Bottom -
csbInfoOfPrompt.srWindow.Top + 1 );
srRead.Right = ( SHORT )( csbInfoOfPrompt.dwSize.X - 1 );
coSize.X = csbInfoOfPrompt.dwSize.X;
coSize.Y = srRead.Bottom = wScreenSize;
pcInfo = ( PCHAR_INFO ) malloc( sizeof( CHAR_INFO ) *
( csbInfoOfPrompt.dwSize.X ) * ( wScreenSize ) );
if( pcInfo )
{
while( srRead.Top <= csbInfoOfPrompt.dwSize.Y - 1 )
{
if( ReadConsoleOutput( g_hTelnetPromptConsoleBuffer, pcInfo,
coSize, coBufferStart, &srRead ) )
{
WriteConsoleOutput( g_hSessionConsoleBuffer, pcInfo, coSize, coBufferStart, &srRead );
srRead.Top = ( SHORT ) ( srRead.Top + wScreenSize );
srRead.Bottom = ( SHORT ) ( srRead.Bottom + wScreenSize );
if( srRead.Bottom > csbInfoOfPrompt.dwSize.Y - 1 )
{
srRead.Bottom = ( SHORT ) ( csbInfoOfPrompt.dwSize.Y - 1 );
}
}
else
{
break;
}
}
free( pcInfo );
SetConsoleWindowInfo( g_hSessionConsoleBuffer, TRUE,
&csbInfoOfPrompt.srWindow );
SetConsoleCursorPosition( g_hSessionConsoleBuffer,
csbInfoOfPrompt.dwCursorPosition );
return( TRUE );
}
}
return( FALSE );
}
BOOL QuitTelnet(LPTSTR szCommand)
{
// Exit gracefully.
if( ui.bLogging )
{
//Close file handles if any
CloseLogging();
}
CopyNPastePromptScreen( );
CloseTelnetSession(NULL);
PostMessage(gwi.hwnd, WM_QUIT, 0, 0L);
return TRUE;
}
BOOL PrintStatus( LPTSTR szCommand )
{
TCHAR szHstNam[512];
TCHAR szTermType[81];
if ( fConnected )
{
_snwprintf( szHstNam,511, ( LPTSTR )TEXT("%S"), gwi.nd.szHostName );
Write( szConnectedTo, szHstNam, NULL );
if( gwi.trm.SentTermType != TT_UNKNOWN )
{
_snwprintf(szTermType,80, ( LPTSTR )TEXT("%S"), rgchTermType[gwi.trm.SentTermType]);
Write( szNegoTermType, szTermType, NULL );
}
}
else
{
Write( szNotConnected, NULL );
}
return FALSE;
}