/*++ 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 #include #include #include #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); if (!ReadFile(rPipe ,(TCHAR *)&ssr.MagicNumber,sizeof(ssr.MagicNumber),&tmp,NULL) || (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; if (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); } }