windows-nt/Source/XPSP1/NT/sdktools/wsremote/client.c
2020-09-26 16:20:57 +08:00

840 lines
18 KiB
C

/*++
Copyright (C) Microsoft Corporation, 1992 - 1999
Module Name:
Client.c
Abstract:
The Client component of Remote. Connects to the remote
server using named pipes. It sends its stdin to
the server and output everything from server to
its stdout.
Author:
Rajivendra Nath (rajnath) 2-Jan-1992
Environment:
Console App. User mode.
Revision History:
--*/
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <string.h>
#include "Remote.h"
HANDLE*
EstablishSession(
TCHAR *server,
TCHAR *pipe
);
SOCKET*
SockEstablishSession(
TCHAR *server,
TCHAR *pipe
);
DWORD
GetServerOut(
PVOID *Noarg
);
DWORD
SockGetServerOut(
PVOID *Noarg
);
DWORD
SendServerInp(
PVOID *Noarg
);
DWORD
SockSendServerInp(
PVOID *Noarg
);
BOOL
FilterClientInp(
TCHAR *buff,
int count
);
BOOL
SockFilterClientInp(
TCHAR *buff,
int count
);
BOOL
Mych(
DWORD ctrlT
);
BOOL
SockMych(
DWORD ctrlT
);
VOID
SendMyInfo(
PHANDLE Pipes
);
VOID
SockSendMyInfo(
SOCKET MySocket
);
HANDLE iothreads[2];
HANDLE MyStdInp;
HANDLE MyStdOut;
HANDLE ReadPipe;
HANDLE WritePipe;
SOCKET RWSocket;
CONSOLE_SCREEN_BUFFER_INFO csbi;
TCHAR MyEchoStr[30];
BOOL CmdSent;
DWORD LinesToSend=LINESTOSEND;
VOID
Client(
TCHAR* Server,
TCHAR* Pipe
)
{
HANDLE *Connection;
DWORD tid;
MyStdInp=GetStdHandle(STD_INPUT_HANDLE);
MyStdOut=GetStdHandle(STD_OUTPUT_HANDLE);
_tprintf(TEXT("****************************************\n"));
_tprintf(TEXT("*********** WSREMOTE ************\n"));
_tprintf(TEXT("*********** CLIENT ************\n"));
_tprintf(TEXT("****************************************\n"));
if ((Connection=EstablishSession(Server,Pipe))==NULL)
return;
ReadPipe=Connection[0];
WritePipe=Connection[1];
SetConsoleCtrlHandler((PHANDLER_ROUTINE)Mych,TRUE);
// Start Thread For Server --> Client Flow
if ((iothreads[0]=CreateThread((LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)GetServerOut, // Thread procedure.
(LPVOID)NULL, // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&tid))==NULL) // Thread identifier.
{
Errormsg(TEXT("Could Not Create rwSrv2Cl Thread"));
return;
}
//
// Start Thread for Client --> Server Flow
//
if ((iothreads[1]=CreateThread((LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)SendServerInp, // Thread procedure.
(LPVOID)NULL, // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&tid))==NULL) // Thread identifier.
{
Errormsg(TEXT("Could Not Create rwSrv2Cl Thread"));
return;
}
WaitForMultipleObjects(2,iothreads,FALSE,INFINITE);
TerminateThread(iothreads[0],1);
TerminateThread(iothreads[1],1);
_tprintf(TEXT("*** SESSION OVER ***\n"));
}
VOID
SockClient(
TCHAR* Server,
TCHAR* Pipe
)
{
SOCKET *Connection;
DWORD tid;
int nRet;
MyStdInp=GetStdHandle(STD_INPUT_HANDLE);
MyStdOut=GetStdHandle(STD_OUTPUT_HANDLE);
_tprintf(TEXT("**************************************\n"));
_tprintf(TEXT("*********** WSREMOTE ************\n"));
_tprintf(TEXT("*********** CLIENT(IP) ************\n"));
_tprintf(TEXT("**************************************\n"));
if ((Connection=SockEstablishSession(Server,Pipe))==NULL)
return;
RWSocket = *Connection;
SetConsoleCtrlHandler((PHANDLER_ROUTINE)SockMych,TRUE);
// Start Thread For Server --> Client Flow
if ((iothreads[0]=CreateThread((LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)SockGetServerOut, // Thread procedure.
(LPVOID)NULL, // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&tid))==NULL) // Thread identifier.
{
Errormsg(TEXT("Could Not Create rwSrv2Cl Thread"));
return;
}
//
// Start Thread for Client --> Server Flow
//
if ((iothreads[1]=CreateThread((LPSECURITY_ATTRIBUTES)NULL, // No security attributes.
(DWORD)0, // Use same stack size.
(LPTHREAD_START_ROUTINE)SockSendServerInp, // Thread procedure.
(LPVOID)NULL, // Parameter to pass.
(DWORD)0, // Run immediately.
(LPDWORD)&tid))==NULL) // Thread identifier.
{
Errormsg(TEXT("Could Not Create rwSrv2Cl Thread"));
return;
}
WaitForMultipleObjects(2,iothreads,FALSE,INFINITE);
TerminateThread(iothreads[0],1);
TerminateThread(iothreads[1],1);
// _tprintf(TEXT("Calling WSACleanup()....\n"));
nRet = WSACleanup();
_tprintf(TEXT("*** SESSION OVER ***\n"));
}
DWORD
GetServerOut(
PVOID *Noarg
)
{
TCHAR buffin[200];
DWORD dread=0,tmp;
while(ReadFile(ReadPipe,buffin,200,&dread,NULL))
{
if (dread!=0)
{
if (!WriteFile(MyStdOut,buffin,dread,&tmp,NULL))
break;
}
}
return(1);
}
DWORD
SockGetServerOut(
PVOID *Noarg
)
{
TCHAR buffin[200];
DWORD dread=0,tmp;
while(ReadSocket(RWSocket,buffin,200,&dread))
{
if (dread!=0)
{
if (!WriteFile(MyStdOut,buffin,dread,&tmp,NULL))
break;
}
}
return(1);
}
DWORD
SendServerInp(
PVOID *Noarg
)
{
TCHAR buff[200];
DWORD dread,dwrote;
SetLastError(0);
while(ReadFile(MyStdInp,buff,200,&dread,NULL))
{
if (FilterClientInp(buff,dread))
continue;
if (!WriteFile(WritePipe,buff,dread,&dwrote,NULL))
break;
}
return(0);
}
DWORD
SockSendServerInp(
PVOID *Noarg
)
{
TCHAR buff[200];
DWORD dread,dwrote;
SetLastError(0);
while(ReadFile(MyStdInp,buff,200,&dread,NULL))
{
if (SockFilterClientInp(buff,dread))
continue;
if (!WriteSocket(RWSocket,buff,dread,&dwrote))
break;
memset(buff, 0, sizeof(buff));
}
return(0);
}
BOOL
SockSendAuth(
SOCKET s
)
{
TCHAR EncodeBuffer[1024];
TCHAR * pEncodeBuffer;
TCHAR UserBuffer[1024];
// TCHAR * String = UserBuffer;
DWORD dwrote;
int len;
BOOL bRet;
SetLastError(0);
memset(EncodeBuffer, 0, sizeof(EncodeBuffer));
_stprintf( UserBuffer,
TEXT("%s:%s"),
Username,
Password);
pEncodeBuffer = EncodeBuffer + _tcslen(EncodeBuffer);
len = _tcslen(UserBuffer);
Base64Encode(UserBuffer, _tcslen(UserBuffer), pEncodeBuffer);
len = _tcslen(pEncodeBuffer);
bRet = WriteSocket(s,pEncodeBuffer,len,&dwrote);
return TRUE;
}
BOOL
FilterClientInp(
TCHAR *buff,
int count
)
{
if (count==0)
return(TRUE);
if (buff[0]==2) //Adhoc screening of ^B so that i386kd/mipskd
return(TRUE);//do not terminate.
if (buff[0]==COMMANDCHAR)
{
switch (buff[1])
{
case 'k':
case 'K':
case 'q':
case 'Q':
CloseHandle(WritePipe);
return(FALSE);
case 'h':
case 'H':
_tprintf(TEXT("%cM : Send Message\n"),COMMANDCHAR);
_tprintf(TEXT("%cP : Show Popup on Server\n"),COMMANDCHAR);
_tprintf(TEXT("%cS : Status of Server\n"),COMMANDCHAR);
_tprintf(TEXT("%cQ : Quit client\n"),COMMANDCHAR);
_tprintf(TEXT("%cH : This Help\n"),COMMANDCHAR);
return(TRUE);
default:
return(FALSE);
}
}
return(FALSE);
}
BOOL
SockFilterClientInp(
TCHAR *buff,
int count
)
{
int nRet;
if (count==0)
return(TRUE);
if (buff[0]==2) //Adhoc screening of ^B so that i386kd/mipskd
return(TRUE);//do not terminate.
if (buff[0]==COMMANDCHAR)
{
switch (buff[1])
{
case 'k':
case 'K':
case 'q':
case 'Q':
nRet = shutdown(RWSocket, SD_BOTH);
if (nRet == SOCKET_ERROR)
_tprintf(TEXT("** shutdown()..error %d"), WSAGetLastError());
closesocket(RWSocket);
return(FALSE);
case 'h':
case 'H':
_tprintf(TEXT("%cM : Send Message\n"),COMMANDCHAR);
_tprintf(TEXT("%cP : Show Popup on Server\n"),COMMANDCHAR);
_tprintf(TEXT("%cS : Status of Server\n"),COMMANDCHAR);
_tprintf(TEXT("%cQ : Quit client\n"),COMMANDCHAR);
_tprintf(TEXT("%cH : This Help\n"),COMMANDCHAR);
return(TRUE);
default:
return(FALSE);
}
}
return(FALSE);
}
BOOL
Mych(
DWORD ctrlT
)
{
TCHAR c[2];
DWORD tmp;
DWORD send=1;
c[0]=CTRLC;
if (ctrlT==CTRL_C_EVENT)
{
if (!WriteFile(WritePipe,c,send,&tmp,NULL))
{
Errormsg(TEXT("Error Sending ^c\n"));
return(FALSE);
}
return(TRUE);
}
if ((ctrlT==CTRL_BREAK_EVENT)||
(ctrlT==CTRL_CLOSE_EVENT)||
(ctrlT==CTRL_LOGOFF_EVENT)||
(ctrlT==CTRL_SHUTDOWN_EVENT)
)
{
CloseHandle(WritePipe); //Will Shutdown naturally
}
return(FALSE);
}
BOOL
SockMych(
DWORD ctrlT
)
{
TCHAR c[2];
DWORD tmp;
DWORD send=1;
c[0]=CTRLC;
if (ctrlT==CTRL_C_EVENT)
{
if (!WriteSocket(RWSocket,c,send,&tmp))
{
Errormsg(TEXT("Error Sending ^c\n"));
return(FALSE);
}
return(TRUE);
}
if ((ctrlT==CTRL_BREAK_EVENT)||
(ctrlT==CTRL_CLOSE_EVENT)||
(ctrlT==CTRL_LOGOFF_EVENT)||
(ctrlT==CTRL_SHUTDOWN_EVENT)
)
{
CloseHandle(WritePipe); //Will Shutdown naturally
}
return(FALSE);
}
HANDLE*
EstablishSession(
TCHAR *server,
TCHAR *srvpipename
)
{
static HANDLE PipeH[2];
TCHAR pipenameSrvIn[200];
TCHAR pipenameSrvOut[200];
_stprintf(pipenameSrvIn ,SERVER_READ_PIPE ,server,srvpipename);
_stprintf(pipenameSrvOut,SERVER_WRITE_PIPE,server,srvpipename);
if ((INVALID_HANDLE_VALUE==(PipeH[0]=CreateFile(pipenameSrvOut,
GENERIC_READ ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL))) ||
(INVALID_HANDLE_VALUE==(PipeH[1]=CreateFile(pipenameSrvIn ,
GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)))) {
DWORD Err=GetLastError();
TCHAR msg[128];
Errormsg(TEXT("*** Unable to Connect ***"));
//
// Print a helpful message
//
switch(Err)
{
case 2: _stprintf(msg,TEXT("Invalid PipeName %s"),srvpipename);break;
case 53:_stprintf(msg,TEXT("Server %s not found"),server);break;
default:
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, Err, 0, msg, 128, NULL);
break;
}
_tprintf(TEXT("Diagnosis:%s\n"),msg);
return(NULL);
}
_tprintf(TEXT("Connected..\n\n"));
SendMyInfo(PipeH);
return(PipeH);
}
SOCKET*
SockEstablishSession(
TCHAR *server,
TCHAR *srvpipename
)
{
static SOCKET Socket;
int nRet;
LPHOSTENT lpHostEntry = NULL;
SOCKADDR_IN sa;
WORD wVersionRequested = MAKEWORD(1,1);
WSADATA wsaData;
unsigned short usPort;
#ifdef UNICODE
int nStrLen;
#endif
//
// Initialize WinSock
//
nRet = WSAStartup(wVersionRequested, &wsaData);
if (nRet)
{
_tprintf(TEXT("Initialize WinSock Failed"));
return NULL;
}
// Check version
if (wsaData.wVersion != wVersionRequested)
{
_tprintf(TEXT("Wrong WinSock Version"));
return NULL;
}
//
// Lookup host
//
#ifdef UNICODE
nStrLen = lstrlen( server );
if (nStrLen)
{
char * pszAnsiStr = (char *)malloc( nStrLen + 1 );
if (pszAnsiStr)
{
int nErr = WideCharToMultiByte( CP_THREAD_ACP,
WC_COMPOSITECHECK,
server,
-1,
pszAnsiStr,
nStrLen,
NULL,
NULL );
if (!nErr)
{
DWORD dwErr = GetLastError();
switch( dwErr )
{
case ERROR_INSUFFICIENT_BUFFER:
_tprintf(TEXT("error: gethostbyname-- WideCharToMultiByte Error: ERROR_INSUFFICIENT_BUFFER"));
break;
case ERROR_INVALID_FLAGS:
_tprintf(TEXT("error: gethostbyname-- WideCharToMultiByte Error: ERROR_INVALID_FLAGS"));
break;
case ERROR_INVALID_PARAMETER:
_tprintf(TEXT("error: gethostbyname-- WideCharToMultiByte Error: ERROR_INVALID_PARAMETER"));
break;
}
free( pszAnsiStr );
return NULL;
}
lpHostEntry = gethostbyname( pszAnsiStr );
free( pszAnsiStr );
}
}
#else
lpHostEntry = gethostbyname( server );
#endif
if (lpHostEntry == NULL)
{
_tprintf(TEXT("wsremote: gethostbyname() error "));
return NULL;
}
//
// Fill in the server address structure
//
sa.sin_family = AF_INET;
sa.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list);
usPort = (unsigned short)_ttoi( srvpipename );
sa.sin_port = htons(usPort);
//
// Create a TCP/IP stream socket
//
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (Socket == INVALID_SOCKET)
{
_tprintf(TEXT("socket()"));
return NULL;
}
//
// Request a connection
//
nRet = connect(Socket,
(LPSOCKADDR)&sa,
sizeof(SOCKADDR_IN));
if (nRet == SOCKET_ERROR)
{
int iWSAErr;
iWSAErr = WSAGetLastError();
_tprintf( TEXT("connect(), Error: %d"), iWSAErr );
return NULL;
}
SockSendMyInfo(Socket);
return(&Socket);
}
VOID
SendMyInfo(
PHANDLE pipeH
)
{
HANDLE rPipe=pipeH[0];
HANDLE wPipe=pipeH[1];
DWORD hostlen=HOSTNAMELEN-1;
WORD BytesToSend=sizeof(SESSION_STARTUPINFO);
DWORD tmp;
SESSION_STARTUPINFO ssi;
SESSION_STARTREPLY ssr;
DWORD BytesToRead;
TCHAR *buff;
ssi.Size=BytesToSend;
ssi.Version=VERSION;
GetComputerName((TCHAR *)ssi.ClientName,&hostlen);
ssi.LinesToSend=LinesToSend;
ssi.Flag=ClientToServerFlag;
{
DWORD NewCode=MAGICNUMBER;
TCHAR Name[15];
_tcscpy(Name,(TCHAR *)ssi.ClientName);
memcpy(&Name[11],(TCHAR *)&NewCode,sizeof(NewCode));
WriteFile(wPipe,(TCHAR *)Name,HOSTNAMELEN-1,&tmp,NULL);
ReadFile(rPipe ,(TCHAR *)&ssr.MagicNumber,sizeof(ssr.MagicNumber),&tmp,NULL);
if (ssr.MagicNumber!=MAGICNUMBER)
{
_tprintf(TEXT("WSREMOTE FAILED TO CONNECT TO SERVER..\n"));
WriteFile(MyStdOut,(TCHAR *)&ssr.MagicNumber,sizeof(ssr.MagicNumber),&tmp,NULL);
return;
}
//Get Rest of the info-its not the old server
ReadFixBytes(rPipe,(TCHAR *)&ssr.Size,sizeof(ssr.Size),0);
ReadFixBytes(rPipe,(TCHAR *)&ssr.FileSize,sizeof(ssr)-sizeof(ssr.FileSize)-sizeof(ssr.MagicNumber),0);
}
if (!WriteFile(wPipe,(TCHAR *)&ssi,BytesToSend,&tmp,NULL))
{
Errormsg(TEXT("INFO Send Error"));
return;
}
BytesToRead=MINIMUM(ssr.FileSize,ssi.LinesToSend*CHARS_PER_LINE);
buff=calloc(BytesToRead+1,1);
if (buff!=NULL)
{
DWORD bytesread=0;
ReadFile(rPipe,buff,BytesToRead,&bytesread,NULL);
WriteFile(MyStdOut,buff,bytesread,&tmp,NULL);
free(buff);
}
}
VOID
SockSendMyInfo(
SOCKET MySocket
)
{
BOOL bRet;
#ifdef UNICODE
char szAnsiName[HOSTNAMELEN];
#endif
DWORD hostlen = HOSTNAMELEN-1;
DWORD BytesToRead;
DWORD tmp;
DWORD NewCode = MAGICNUMBER;
SESSION_STARTUPINFO ssi;
SESSION_STARTREPLY ssr;
int nRet;
TCHAR Name[HOSTNAMELEN];
TCHAR * buff;
WORD BytesToSend = sizeof(SESSION_STARTUPINFO);
ssi.Size=BytesToSend;
ssi.Version=VERSION;
GetComputerName((TCHAR *)ssi.ClientName,&hostlen);
ssi.LinesToSend=LinesToSend;
ssi.Flag=ClientToServerFlag;
bRet = SockSendAuth(MySocket);
// append on magic number
_tcscpy(Name, ssi.ClientName);
#ifdef UNICODE
GetAnsiStr( (TCHAR *)&Name, (char *)&szAnsiName, HOSTNAMELEN );
memcpy(&szAnsiName[11], &NewCode, sizeof(DWORD) );
WriteSocketA( MySocket,(char *)&szAnsiName,HOSTNAMELEN-1,&tmp);
#else
memcpy(&Name[11], &NewCode, sizeof(DWORD) );
WriteSocket( MySocket,(TCHAR *)Name,HOSTNAMELEN-1,&tmp);
#endif
ReadSocket(MySocket ,(TCHAR *)&ssr.MagicNumber,sizeof(ssr.MagicNumber),&tmp);
if (ssr.MagicNumber!=MAGICNUMBER)
{
_tprintf(TEXT("WSREMOTE FAILED TO CONNECT TO SERVER..\n"));
nRet = shutdown(MySocket, SD_BOTH);
if (nRet == SOCKET_ERROR)
_tprintf(TEXT("** shutdown()..error %d"), WSAGetLastError());
closesocket(MySocket);
return;
}
//Get Rest of the info-its not the old server
SockReadFixBytes(MySocket,(TCHAR *)&ssr.Size,sizeof(ssr.Size),0);
SockReadFixBytes(MySocket,(TCHAR *)&ssr.FileSize,sizeof(ssr)-sizeof(ssr.FileSize)-sizeof(ssr.MagicNumber),0);
if (!WriteSocket(MySocket,(TCHAR *)&ssi,BytesToSend,&tmp))
{
_tprintf(TEXT("INFO Send Error"));
return;
}
BytesToRead=MINIMUM(ssr.FileSize,ssi.LinesToSend*CHARS_PER_LINE);
buff=calloc(BytesToRead+1,1);
if (buff!=NULL)
{
DWORD bytesread=0;
ReadSocket(MySocket,buff,BytesToRead,&bytesread);
WriteFile(MyStdOut,buff,bytesread,&tmp,NULL);
free(buff);
}
}