|
|
/*++
Copyright (C) Microsoft Corporation, 1993 - 1999
Module Name:
Remote.c
Abstract:
This module contains the main() entry point for Remote. Calls the Server or the Client depending on the first parameter.
Author:
Rajivendra Nath (rajnath) 2-Jan-1993
Environment:
Console App. User mode.
Revision History:
--*/
#include <stdio.h>
#include <stdlib.h>
#include "Remote.h"
TCHAR HostName[HOSTNAMELEN]; TCHAR * ChildCmd; TCHAR* PipeName; TCHAR* ServerName; TCHAR* Username; TCHAR* Password; HANDLE MyOutHandle; BOOL bIPLocked=FALSE;
BOOL IsAdvertise=TRUE; DWORD ClientToServerFlag;
TCHAR* ColorList[]={ TEXT("black"), TEXT("blue"), TEXT("green"), TEXT("cyan"), TEXT("red"), TEXT("purple"), TEXT("yellow"), TEXT("white"), TEXT("lblack"), TEXT("lblue"), TEXT("lgreen"), TEXT("lcyan"), TEXT("lred"), TEXT("lpurple"), TEXT("lyellow"), TEXT("lwhite") };
WORD GetColorNum( TCHAR* color );
VOID SetColor( WORD attr );
BOOL GetNextConnectInfo( TCHAR** SrvName, TCHAR** PipeName );
CONSOLE_SCREEN_BUFFER_INFO csbiOriginal;
int _cdecl _tmain(int argc, TCHAR *argv[]) { WORD RunType; // Server or Client end of Remote
DWORD len=HOSTNAMELEN-1; int i, FirstArg;
BOOL bSetAttrib=FALSE; // Change Console Attributes
BOOL bPromptForArgs=FALSE; // Is /P option
BOOL bIPSession=TRUE; // Is /N for Named Pipes
TCHAR szTitle[100]; // New Title
TCHAR szOrgTitle[100]; // Old Title
WORD wAttrib; // Console Attributes
GetComputerName((LPTSTR)HostName,&len);
MyOutHandle=GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(MyOutHandle,&csbiOriginal);
//
// Parameter Processing
//
// For Server:
// Remote /S <Executable> <PipeName> [Optional Params]
//
// For Client:
// Remote /C <Server Name> <PipeName> [Optional Params]
// or
// Remote /P
// This will loop continously prompting for different
// Servers and Pipename
if ((argc<2)||((argv[1][0]!='/')&&(argv[1][0]!='-'))) {
DisplayServerHlp(); DisplayClientHlp(); return(1); }
switch(argv[1][1]) {
case 'c': case 'C':
//
// Is Client End of Remote
//
if ((argc<4)||((argv[1][0]!='/')&&(argv[1][0]!='-'))) {
DisplayServerHlp(); DisplayClientHlp(); return(1); }
ServerName=argv[2]; PipeName=argv[3]; FirstArg=4; RunType=REMOTE_CLIENT; break;
case 'p': case 'P':
//
// Is Client End of Remote
//
bPromptForArgs=TRUE; RunType=REMOTE_CLIENT; FirstArg=2; break;
case 's': case 'S': //
// Is Server End of Remote
//
if ((argc<4)||((argv[1][0]!='/')&&(argv[1][0]!='-'))) {
DisplayServerHlp(); DisplayClientHlp(); return(1); }
ChildCmd=argv[2]; PipeName=argv[3]; FirstArg=4;
RunType=REMOTE_SERVER; break;
default: DisplayServerHlp(); DisplayClientHlp(); return(1); }
//
// Save Existing Values
//
//
//Colors /f <ForeGround> /b <BackGround>
//
wAttrib=csbiOriginal.wAttributes;
//
//Title /T Title
//
GetConsoleTitle( szOrgTitle, lstrlen( szOrgTitle) );
if (RunType==REMOTE_SERVER) { //
// Base Name of Executable
// For setting the title
//
TCHAR *tcmd=ChildCmd;
while ((*tcmd!=' ') &&(*tcmd!=0)) tcmd++; while ((tcmd!=ChildCmd)&&(*tcmd!='\\'))tcmd--;
_stprintf( szTitle, TEXT("%-8.8s [WSRemote /C %s %s]"), tcmd, HostName, PipeName); }
//
//Process Common (Optional) Parameters
//
for (i=FirstArg;i<argc;i++) {
if ((argv[i][0]!='/')&&(argv[i][0]!='-')) { _tprintf( TEXT("Invalid parameter %s:Ignoring\n"),argv[i]); continue; }
switch(argv[i][1]) { case 'u': // Only Valid for Server End
case 'U': // Username To Use to Connect to Session
i++; if (i>=argc) { _tprintf( TEXT("Incomplete Param %s..Ignoring\n"),argv[i-1]); break; } Username=(argv[i]); break;
case 'p': // Only Valid for Server End
case 'P': // Password To Use to Connect to Session
i++; if (i>=argc) { _tprintf( TEXT("Incomplete Param %s..Ignoring\n"),argv[i-1]); break; } Password=(argv[i]); break;
case 'l': // Only Valid for client End
case 'L': // Max Number of Lines to recieve from Server
i++; if (i>=argc) { _tprintf(TEXT("Incomplete Param %s..Ignoring\n"),argv[i-1]); break; } LinesToSend=(DWORD)_ttoi(argv[i])+1; break;
case 't': // Title to be set instead of the default
case 'T': i++; if (i>=argc) { _tprintf(TEXT("Incomplete Param %s..Ignoring\n"),argv[i-1]); break; } _stprintf( szTitle, TEXT("%s"),argv[i]); break;
case 'b': // Background color
case 'B': i++; if (i>=argc) { _tprintf(TEXT("Incomplete Param %s..Ignoring\n"),argv[i-1]); break; } { WORD col=GetColorNum(argv[i]); if (col!=0xffff) { bSetAttrib=TRUE; wAttrib=col<<4|(wAttrib&0x000f); } break; }
case 'f': // Foreground color
case 'F': i++; if (i>=argc) { _tprintf(TEXT("Incomplete Param %s..Ignoring\n"),argv[i-1]); break; } { WORD col=GetColorNum(argv[i]); if (col!=0xffff) { bSetAttrib=TRUE; wAttrib=col|(wAttrib&0x00f0); } break; }
case 'q': case 'Q': IsAdvertise=FALSE; ClientToServerFlag|=0x80000000; break; case 'n': case 'N': bIPSession=FALSE; break; case 'i': case 'I': bIPLocked=TRUE; break; default: _tprintf(TEXT("Unknown Parameter=%s %s\n"),argv[i-1],argv[i]); break;
}
}
//
//Now Set various Parameters
//
//
//Colors
//
SetColor(wAttrib);
if (RunType==REMOTE_CLIENT) { BOOL done=FALSE;
//
// Set Client end defaults and start client
//
while(!done) { if (!bPromptForArgs || GetNextConnectInfo(&ServerName,&PipeName) ) { _stprintf( szTitle, TEXT("WSRemote /C %s %s"),ServerName,PipeName); SetConsoleTitle(szTitle);
if (!bIPSession) { //
// Start Client (Client.C)
//
Client(ServerName,PipeName); } else { SockClient(ServerName,PipeName); } } done=!bPromptForArgs; } }
if (RunType==REMOTE_SERVER) { SetConsoleTitle(szTitle);
//
// Start Server (Server.C)
//
Server(ChildCmd,PipeName); }
//
//Reset Colors
//
SetColor(csbiOriginal.wAttributes); SetConsoleTitle(szOrgTitle);
ExitProcess(0); return( 1 ); } /*************************************************************/ VOID ErrorExit( TCHAR* str ) { _tprintf(TEXT("Error-%d:%s\n"),GetLastError(),str); ExitProcess(1); }
/*************************************************************/ DWORD ReadFixBytes( HANDLE hRead, TCHAR* Buffer, DWORD ToRead, DWORD TimeOut //ignore for timebeing
) { DWORD xyzBytesRead=0; DWORD xyzBytesToRead=ToRead; TCHAR* xyzbuff=Buffer;
while(xyzBytesToRead!=0) { if (!ReadFile(hRead,xyzbuff,xyzBytesToRead,&xyzBytesRead,NULL)) { return(xyzBytesToRead); }
xyzBytesToRead-=xyzBytesRead; xyzbuff+=xyzBytesRead; } return(0);
} /*************************************************************/
/*************************************************************/ DWORD SockReadFixBytes( SOCKET hSocket, TCHAR* Buffer, DWORD ToRead, DWORD TimeOut //ignore for timebeing
) { DWORD xyzBytesRead=0; DWORD xyzBytesToRead=ToRead; TCHAR* xyzbuff=Buffer;
while(xyzBytesToRead!=0) { if (!ReadSocket(hSocket,xyzbuff,xyzBytesToRead,&xyzBytesRead)) { return(xyzBytesToRead); }
xyzBytesToRead-=xyzBytesRead; xyzbuff+=xyzBytesRead; } return(0);
} /*************************************************************/
VOID DisplayClientHlp() { _tprintf(TEXT("\n To Start the CLIENT end of WSREMOTE\n")); _tprintf(TEXT(" ---------------------------------\n")); _tprintf(TEXT(" Syntax : WSREMOTE /C <ServerName> <Unique Id> [Param]\n")); _tprintf(TEXT(" Example: WSREMOTE /C iisdebug 70\n")); _tprintf(TEXT(" This would connect to a server session on \n")); _tprintf(TEXT(" iisdebug with id \"70\" if there was a\n")); _tprintf(TEXT(" WSREMOTE /S <\"Cmd\"> 70\n")); _tprintf(TEXT(" started on the machine iisdebug.\n\n")); _tprintf(TEXT(" To Exit: %cQ (Leaves the Remote Server Running)\n"),COMMANDCHAR); _tprintf(TEXT(" [Param]: /L <# of Lines to Get>\n")); _tprintf(TEXT(" [Param]: /F <Foreground color eg blue, lred..>\n")); _tprintf(TEXT(" [Param]: /B <Background color eg cyan, lwhite..>\n")); _tprintf(TEXT(" [Param]: /N (Connect over Named Pipes)\n")); _tprintf(TEXT(" [Param]: /U <Username> (Username to connect)\n")); _tprintf(TEXT(" [Param]: /P <Password> (Password to connect)\n")); _tprintf(TEXT("\n")); } /*************************************************************/
VOID DisplayServerHlp() {
#define WRITEF2(VArgs) { \
HANDLE xh=GetStdHandle(STD_OUTPUT_HANDLE); \ TCHAR VBuff[256]; \ DWORD tmp; \ _stprintf VArgs; \ WriteFile(xh,VBuff,lstrlen(VBuff),&tmp,NULL); \ } \
_tprintf(TEXT("\n To Start the SERVER end of WSREMOTE\n")); _tprintf(TEXT(" ---------------------------------\n")); _tprintf(TEXT(" Syntax : WSREMOTE /S <\"Cmd\"> <Unique Id or Port Number> [Param]\n")); _tprintf(TEXT(" Syntax : WSREMOTE /S <\"Cmd\"> <Unique Id or Port Number> [Param]\n")); _tprintf(TEXT(" Example: WSREMOTE /S \"cmd.exe\" inetinfo\n")); _tprintf(TEXT(" To interact with this \"Cmd\" \n")); _tprintf(TEXT(" from some other machine\n")); _tprintf(TEXT(" - start the client end by:\n")); _tprintf(TEXT(" REMOTE /C %s PortNum\n\n"),HostName); _tprintf(TEXT(" To Exit: %cK \n"),COMMANDCHAR); _tprintf(TEXT(" [Param]: /F <Foreground color eg yellow, black..>\n")); _tprintf(TEXT(" [Param]: /B <Background color eg lblue, white..>\n")); _tprintf(TEXT(" [Param]: /I (Turns ON IP Blocking)\n")); _tprintf(TEXT(" [Param]: /U <Username> (Username to connect)\n")); _tprintf(TEXT(" [Param]: /P <Password> (Password to connect)\n")); _tprintf(TEXT("\n"));
}
WORD GetColorNum( TCHAR *color ) { WORD wIndex;
_tcslwr(color); for (wIndex=0;wIndex<16;wIndex++) { if (_tcscmp(ColorList[wIndex],color)==0) { return(wIndex); } } return ((WORD)_ttoi(color)); }
VOID SetColor( WORD attr ) { COORD origin={0,0}; DWORD dwrite; FillConsoleOutputAttribute ( MyOutHandle,attr,csbiOriginal.dwSize. X*csbiOriginal.dwSize.Y,origin,&dwrite ); SetConsoleTextAttribute(MyOutHandle,attr); }
BOOL GetNextConnectInfo( TCHAR** SrvName, TCHAR** PipeName ) { static TCHAR szServerName[64]; static TCHAR szPipeName[32]; TCHAR *s;
__try { ZeroMemory(szServerName,64); ZeroMemory(szPipeName,32); SetConsoleTitle( TEXT("Remote - Prompting for next Connection")); _tprintf(TEXT("Debugger machine (server): ")); fflush(stdout);
if (((*SrvName=_getts(szServerName))==NULL)|| (_tcslen(szServerName)==0)) { return(FALSE); }
if (szServerName[0] == COMMANDCHAR && (szServerName[1] == 'q' || szServerName[1] == 'Q') ) { return(FALSE); }
if (s = _tcschr( szServerName, ' ' )) { *s++ = '\0'; while (*s == ' ') { s += 1; } *PipeName=_tcscpy(szPipeName, s); _tprintf(szPipeName); fflush(stdout); } if (_tcslen(szPipeName) == 0) { _tprintf(TEXT("Debuggee machine : ")); fflush(stdout); if ((*PipeName=_getts(szPipeName))==NULL) { return(FALSE); } }
if (s = _tcschr(szPipeName, ' ')) { *s++ = '\0'; }
if (szPipeName[0] == COMMANDCHAR && (szPipeName[1] == 'q' || szPipeName[1] == 'Q') ) { return(FALSE); } _tprintf(TEXT("\n\n")); }
__except(EXCEPTION_EXECUTE_HANDLER) { return(FALSE); // Ignore exceptions
} return(TRUE); }
/*************************************************************/ VOID Errormsg( TCHAR* str ) { _tprintf(TEXT("Error (%d) - %s\n"),GetLastError(),str); }
/*************************************************************/
BOOL ReadSocket(SOCKET s,TCHAR * buff,int len,DWORD* dread) { BOOL bRet = FALSE; DWORD numread;
#ifdef UNICODE
char * pszAnsiStr = (char *)calloc( (len + 1), sizeof(char) );
if (pszAnsiStr) { int nErr; numread = (DWORD)recv( s, pszAnsiStr, len, 0);
if (SOCKET_ERROR != numread) { nErr = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszAnsiStr, len, buff, len );
if (nErr) { *dread = numread; bRet = TRUE; }
//Base64Decode(buff,DecodeBuffer);
}
free( pszAnsiStr ); } #else
numread = (DWORD)recv( s, buff, len, 0);
if (SOCKET_ERROR != numread) { *dread = numread; bRet = TRUE; }
#endif
return bRet; }
// returns TRUE if successful, false otherwise
BOOL WriteSocket( SOCKET s, TCHAR * buff, int len, DWORD* dsent) { BOOL bRet = FALSE; DWORD numsent;
#ifdef UNICODE
int nStrLen = lstrlen( buff );
if (nStrLen) { char * pszAnsiStr = (char *)malloc( nStrLen + 1 );
if (pszAnsiStr) { int nErr = WideCharToMultiByte( CP_ACP, WC_COMPOSITECHECK, buff, nStrLen, pszAnsiStr, nStrLen, NULL, NULL ); if (nErr) { numsent = (DWORD)send(s, pszAnsiStr, nStrLen, 0); if (SOCKET_ERROR != numsent) { *dsent = numsent; bRet = TRUE; } }
//Base64Decode(buff,DecodeBuffer);
free( pszAnsiStr ); } } #else
numsent = (DWORD)send(s, buff, len, 0); if (SOCKET_ERROR != numsent) { *dsent = numsent; bRet = TRUE; }
#endif
return bRet; }
#ifdef UNICODE
// returns TRUE if successful, false otherwise
BOOL WriteSocketA( SOCKET s, char * pszAnsiStr, int len, DWORD * dsent) { BOOL bRet = FALSE; DWORD numsent;
numsent = (DWORD)send(s, pszAnsiStr, len, 0);
if (SOCKET_ERROR != numsent) { *dsent = numsent; bRet = TRUE; }
//Base64Decode(buff,DecodeBuffer);
return bRet; } #endif
////////////////////////////////////////////////
unsigned char Base64Table[64] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'};
VOID Base64Encode( TCHAR * String, DWORD StringLength, TCHAR * EncodeBuffer) { DWORD EncodeDword; int Index;
memset(EncodeBuffer, 0, 2 * StringLength);
Index = 0;
while (StringLength >= 3) { //
// Encode a three byte chunk
//
EncodeDword = (String[0] << 16) & 0xff0000;
EncodeDword += (String[1] << 8) & 0xff00;
EncodeDword += String[2] & 0xff;
EncodeBuffer[Index++] = Base64Table[(EncodeDword >> 18) & 63]; EncodeBuffer[Index++] = Base64Table[(EncodeDword >> 12) & 63]; EncodeBuffer[Index++] = Base64Table[(EncodeDword >> 6) & 63]; EncodeBuffer[Index++] = Base64Table[EncodeDword & 63];
String += 3; StringLength -= 3; }
switch (StringLength) { case 1: EncodeDword = (String[0] << 16) & 0xff0000; EncodeBuffer[Index++] = Base64Table[(EncodeDword >> 18) & 63]; EncodeBuffer[Index++] = Base64Table[(EncodeDword >> 12) & 63]; EncodeBuffer[Index++] = '='; EncodeBuffer[Index++] = '='; break; case 2: EncodeDword = (String[0] << 16) & 0xff0000; EncodeDword += (String[1] << 8) & 0xff00;
EncodeBuffer[Index++] = Base64Table[(EncodeDword >> 18) & 63]; EncodeBuffer[Index++] = Base64Table[(EncodeDword >> 12) & 63]; EncodeBuffer[Index++] = Base64Table[(EncodeDword >> 6) & 63]; EncodeBuffer[Index++] = '='; break; }
EncodeBuffer[Index] = 0;
return; } int GetBase64Index( TCHAR A) { int i;
for (i=0; i<64; i++) { if (Base64Table[i] == A) { return i; } }
return -1; } VOID Base64Decode( TCHAR * String, TCHAR * DecodeBuffer) { DWORD DecodeDword; int Index = 0;
memset(DecodeBuffer, 0, _tcslen(String));
if (_tcslen(String) % 4) { printf("WCAT INTERNAL ERROR %s %d\n", __FILE__, __LINE__); return; }
while (*String) { //
// Decode a four byte chunk
//
if (GetBase64Index(String[0]) < 0) { //
// Invalid string
//
printf("WCAT INTERNAL ERROR %s %d\n", __FILE__, __LINE__); return; }
DecodeDword = ((unsigned int) GetBase64Index(String[0])) << 18;
if (GetBase64Index(String[1]) >= 0) { //
// still more characters
//
DecodeDword += ((unsigned int) GetBase64Index(String[1])) << 12; if (GetBase64Index(String[2]) >= 0) { //
// still more characters
//
DecodeDword += ((unsigned int) GetBase64Index(String[2])) << 6; if (GetBase64Index(String[3]) >= 0) { //
// still more characters
//
DecodeDword += (unsigned int) GetBase64Index(String[3]); DecodeBuffer[Index++] = (unsigned char) ((DecodeDword >> 16) & 0xff); DecodeBuffer[Index++] = (unsigned char) ((DecodeDword >> 8) & 0xff); DecodeBuffer[Index++] = (unsigned char) (DecodeDword & 0xff); } else { DecodeBuffer[Index++] = (unsigned char) ((DecodeDword >> 16) & 0xff); DecodeBuffer[Index++] = (unsigned char) ((DecodeDword >> 8) & 0xff); } } else { DecodeBuffer[Index++] = (unsigned char) ((DecodeDword >> 16) & 0xff); } }
String += 4; }
return; }
VOID SplitUserName( TCHAR * FullName, TCHAR * Domain, TCHAR * UserName) { TCHAR * Slash; Slash = _tcsstr(FullName, TEXT(":"));
if (Slash) { // there is a domain name
*Slash = 0; _tcscpy(Domain, FullName); _tcscpy(UserName, Slash+1); *Slash = ':'; } else { *Domain = 0; _tcscpy(UserName, FullName); } }
#ifdef UNICODE
// caller must free buffer
WCHAR * inet_ntoaw( struct in_addr stInet ) { char * pszAnsiInetStr = inet_ntoa( stInet );
int nStrLen = strlen( pszAnsiInetStr );
WCHAR * pszInetStr = (WCHAR *)calloc( (nStrLen + 1), sizeof( TCHAR ));
int nErr = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszAnsiInetStr, nStrLen, pszInetStr, nStrLen );
if (!nErr) { free( pszInetStr ); pszInetStr = NULL; }
return pszInetStr; }
BOOL ReadFileW( HANDLE hFile, // handle of file to read
WCHAR * pszBuffer, // pointer to buffer that receives data
DWORD dwLength, // number of bytes to read
LPDWORD pdwRead, // pointer to number of bytes read
LPOVERLAPPED pData // pointer to structure for data
) { BOOL bRet = FALSE; char * pszAnsi = (char *)calloc( dwLength + 1, sizeof(char *));
if (pszAnsi) { bRet = ReadFile( hFile, pszAnsi, dwLength, pdwRead, pData);
if (bRet) { int nErr = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszAnsi, *pdwRead, pszBuffer, *pdwRead );
if (!nErr) { bRet = FALSE; } }
free( pszAnsi ); }
return bRet; }
BOOL WriteFileW( HANDLE hFile, // handle to file to write to
WCHAR * pszBuffer, // pointer to data to write to file
DWORD dwWrite, // number of bytes to write
LPDWORD pdwWritten, // pointer to number of bytes written
LPOVERLAPPED pData // pointer to structure for overlapped I/O
) { BOOL bRet = FALSE; int nStrLen = lstrlen( pszBuffer );
if (nStrLen) { char * pszAnsiStr = (char *)malloc( nStrLen + 1 );
if (pszAnsiStr) { int nErr = WideCharToMultiByte( CP_ACP, WC_COMPOSITECHECK, pszBuffer, nStrLen, pszAnsiStr, nStrLen, NULL, NULL ); if (nErr) { bRet = WriteFile( hFile, pszAnsiStr, dwWrite, pdwWritten, pData); }
free( pszAnsiStr ); } }
return bRet; }
// caller most free buffer
BOOL GetAnsiStr( WCHAR * pszWideStr, char * pszAnsiStr, UINT uBufSize ) { BOOL bRet = FALSE; if (pszWideStr && pszAnsiStr) { int nStrLen = lstrlen( pszWideStr );
if (nStrLen) { int nErr = WideCharToMultiByte( CP_ACP, WC_COMPOSITECHECK, pszWideStr, nStrLen, pszAnsiStr, uBufSize - 1, NULL, NULL ); if (nErr) { pszAnsiStr[nStrLen] = '\0'; bRet = TRUE; } } } return bRet; } #endif
|